1fafd8bceSBlue Swirl /* 2fafd8bceSBlue Swirl * Helpers for loads and stores 3fafd8bceSBlue Swirl * 4fafd8bceSBlue Swirl * Copyright (c) 2003-2005 Fabrice Bellard 5fafd8bceSBlue Swirl * 6fafd8bceSBlue Swirl * This library is free software; you can redistribute it and/or 7fafd8bceSBlue Swirl * modify it under the terms of the GNU Lesser General Public 8fafd8bceSBlue Swirl * License as published by the Free Software Foundation; either 9fafd8bceSBlue Swirl * version 2 of the License, or (at your option) any later version. 10fafd8bceSBlue Swirl * 11fafd8bceSBlue Swirl * This library is distributed in the hope that it will be useful, 12fafd8bceSBlue Swirl * but WITHOUT ANY WARRANTY; without even the implied warranty of 13fafd8bceSBlue Swirl * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14fafd8bceSBlue Swirl * Lesser General Public License for more details. 15fafd8bceSBlue Swirl * 16fafd8bceSBlue Swirl * You should have received a copy of the GNU Lesser General Public 17fafd8bceSBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18fafd8bceSBlue Swirl */ 19fafd8bceSBlue Swirl 20db5ebe5fSPeter Maydell #include "qemu/osdep.h" 21fafd8bceSBlue Swirl #include "cpu.h" 226850811eSRichard Henderson #include "tcg.h" 232ef6175aSRichard Henderson #include "exec/helper-proto.h" 2463c91552SPaolo Bonzini #include "exec/exec-all.h" 25f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h" 260cc1f4bfSRichard Henderson #include "asi.h" 27fafd8bceSBlue Swirl 28fafd8bceSBlue Swirl //#define DEBUG_MMU 29fafd8bceSBlue Swirl //#define DEBUG_MXCC 30fafd8bceSBlue Swirl //#define DEBUG_UNALIGNED 31fafd8bceSBlue Swirl //#define DEBUG_UNASSIGNED 32fafd8bceSBlue Swirl //#define DEBUG_ASI 33fafd8bceSBlue Swirl //#define DEBUG_CACHE_CONTROL 34fafd8bceSBlue Swirl 35fafd8bceSBlue Swirl #ifdef DEBUG_MMU 36fafd8bceSBlue Swirl #define DPRINTF_MMU(fmt, ...) \ 37fafd8bceSBlue Swirl do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0) 38fafd8bceSBlue Swirl #else 39fafd8bceSBlue Swirl #define DPRINTF_MMU(fmt, ...) do {} while (0) 40fafd8bceSBlue Swirl #endif 41fafd8bceSBlue Swirl 42fafd8bceSBlue Swirl #ifdef DEBUG_MXCC 43fafd8bceSBlue Swirl #define DPRINTF_MXCC(fmt, ...) \ 44fafd8bceSBlue Swirl do { printf("MXCC: " fmt , ## __VA_ARGS__); } while (0) 45fafd8bceSBlue Swirl #else 46fafd8bceSBlue Swirl #define DPRINTF_MXCC(fmt, ...) do {} while (0) 47fafd8bceSBlue Swirl #endif 48fafd8bceSBlue Swirl 49fafd8bceSBlue Swirl #ifdef DEBUG_ASI 50fafd8bceSBlue Swirl #define DPRINTF_ASI(fmt, ...) \ 51fafd8bceSBlue Swirl do { printf("ASI: " fmt , ## __VA_ARGS__); } while (0) 52fafd8bceSBlue Swirl #endif 53fafd8bceSBlue Swirl 54fafd8bceSBlue Swirl #ifdef DEBUG_CACHE_CONTROL 55fafd8bceSBlue Swirl #define DPRINTF_CACHE_CONTROL(fmt, ...) \ 56fafd8bceSBlue Swirl do { printf("CACHE_CONTROL: " fmt , ## __VA_ARGS__); } while (0) 57fafd8bceSBlue Swirl #else 58fafd8bceSBlue Swirl #define DPRINTF_CACHE_CONTROL(fmt, ...) do {} while (0) 59fafd8bceSBlue Swirl #endif 60fafd8bceSBlue Swirl 61fafd8bceSBlue Swirl #ifdef TARGET_SPARC64 62fafd8bceSBlue Swirl #ifndef TARGET_ABI32 63fafd8bceSBlue Swirl #define AM_CHECK(env1) ((env1)->pstate & PS_AM) 64fafd8bceSBlue Swirl #else 65fafd8bceSBlue Swirl #define AM_CHECK(env1) (1) 66fafd8bceSBlue Swirl #endif 67fafd8bceSBlue Swirl #endif 68fafd8bceSBlue Swirl 69fafd8bceSBlue Swirl #define QT0 (env->qt0) 70fafd8bceSBlue Swirl #define QT1 (env->qt1) 71fafd8bceSBlue Swirl 72fafd8bceSBlue Swirl #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) 7315f746ceSArtyom Tarasenko /* Calculates TSB pointer value for fault page size 7415f746ceSArtyom Tarasenko * UltraSPARC IIi has fixed sizes (8k or 64k) for the page pointers 7515f746ceSArtyom Tarasenko * UA2005 holds the page size configuration in mmu_ctx registers */ 76e5673ee4SArtyom Tarasenko static uint64_t ultrasparc_tsb_pointer(CPUSPARCState *env, 77e5673ee4SArtyom Tarasenko const SparcV9MMU *mmu, const int idx) 78fafd8bceSBlue Swirl { 7915f746ceSArtyom Tarasenko uint64_t tsb_register; 8015f746ceSArtyom Tarasenko int page_size; 8115f746ceSArtyom Tarasenko if (cpu_has_hypervisor(env)) { 8215f746ceSArtyom Tarasenko int tsb_index = 0; 83e5673ee4SArtyom Tarasenko int ctx = mmu->tag_access & 0x1fffULL; 84e5673ee4SArtyom Tarasenko uint64_t ctx_register = mmu->sun4v_ctx_config[ctx ? 1 : 0]; 8515f746ceSArtyom Tarasenko tsb_index = idx; 8615f746ceSArtyom Tarasenko tsb_index |= ctx ? 2 : 0; 8715f746ceSArtyom Tarasenko page_size = idx ? ctx_register >> 8 : ctx_register; 8815f746ceSArtyom Tarasenko page_size &= 7; 89e5673ee4SArtyom Tarasenko tsb_register = mmu->sun4v_tsb_pointers[tsb_index]; 9015f746ceSArtyom Tarasenko } else { 9115f746ceSArtyom Tarasenko page_size = idx; 92e5673ee4SArtyom Tarasenko tsb_register = mmu->tsb; 9315f746ceSArtyom Tarasenko } 94fafd8bceSBlue Swirl int tsb_split = (tsb_register & 0x1000ULL) ? 1 : 0; 95fafd8bceSBlue Swirl int tsb_size = tsb_register & 0xf; 96fafd8bceSBlue Swirl 97e5673ee4SArtyom Tarasenko uint64_t tsb_base_mask = (~0x1fffULL) << tsb_size; 98fafd8bceSBlue Swirl 99e5673ee4SArtyom Tarasenko /* move va bits to correct position, 100e5673ee4SArtyom Tarasenko * the context bits will be masked out later */ 101e5673ee4SArtyom Tarasenko uint64_t va = mmu->tag_access >> (3 * page_size + 9); 102fafd8bceSBlue Swirl 103fafd8bceSBlue Swirl /* calculate tsb_base mask and adjust va if split is in use */ 104fafd8bceSBlue Swirl if (tsb_split) { 10515f746ceSArtyom Tarasenko if (idx == 0) { 106fafd8bceSBlue Swirl va &= ~(1ULL << (13 + tsb_size)); 10715f746ceSArtyom Tarasenko } else { 108fafd8bceSBlue Swirl va |= (1ULL << (13 + tsb_size)); 109fafd8bceSBlue Swirl } 110fafd8bceSBlue Swirl tsb_base_mask <<= 1; 111fafd8bceSBlue Swirl } 112fafd8bceSBlue Swirl 113e5673ee4SArtyom Tarasenko return ((tsb_register & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL; 114fafd8bceSBlue Swirl } 115fafd8bceSBlue Swirl 116fafd8bceSBlue Swirl /* Calculates tag target register value by reordering bits 117fafd8bceSBlue Swirl in tag access register */ 118fafd8bceSBlue Swirl static uint64_t ultrasparc_tag_target(uint64_t tag_access_register) 119fafd8bceSBlue Swirl { 120fafd8bceSBlue Swirl return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22); 121fafd8bceSBlue Swirl } 122fafd8bceSBlue Swirl 123fafd8bceSBlue Swirl static void replace_tlb_entry(SparcTLBEntry *tlb, 124fafd8bceSBlue Swirl uint64_t tlb_tag, uint64_t tlb_tte, 125c5f9864eSAndreas Färber CPUSPARCState *env1) 126fafd8bceSBlue Swirl { 127fafd8bceSBlue Swirl target_ulong mask, size, va, offset; 128fafd8bceSBlue Swirl 129fafd8bceSBlue Swirl /* flush page range if translation is valid */ 130fafd8bceSBlue Swirl if (TTE_IS_VALID(tlb->tte)) { 13131b030d4SAndreas Färber CPUState *cs = CPU(sparc_env_get_cpu(env1)); 132fafd8bceSBlue Swirl 133e4d06ca7SArtyom Tarasenko size = 8192ULL << 3 * TTE_PGSIZE(tlb->tte); 134e4d06ca7SArtyom Tarasenko mask = 1ULL + ~size; 135fafd8bceSBlue Swirl 136fafd8bceSBlue Swirl va = tlb->tag & mask; 137fafd8bceSBlue Swirl 138fafd8bceSBlue Swirl for (offset = 0; offset < size; offset += TARGET_PAGE_SIZE) { 13931b030d4SAndreas Färber tlb_flush_page(cs, va + offset); 140fafd8bceSBlue Swirl } 141fafd8bceSBlue Swirl } 142fafd8bceSBlue Swirl 143fafd8bceSBlue Swirl tlb->tag = tlb_tag; 144fafd8bceSBlue Swirl tlb->tte = tlb_tte; 145fafd8bceSBlue Swirl } 146fafd8bceSBlue Swirl 147fafd8bceSBlue Swirl static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr, 148c5f9864eSAndreas Färber const char *strmmu, CPUSPARCState *env1) 149fafd8bceSBlue Swirl { 150fafd8bceSBlue Swirl unsigned int i; 151fafd8bceSBlue Swirl target_ulong mask; 152fafd8bceSBlue Swirl uint64_t context; 153fafd8bceSBlue Swirl 154fafd8bceSBlue Swirl int is_demap_context = (demap_addr >> 6) & 1; 155fafd8bceSBlue Swirl 156fafd8bceSBlue Swirl /* demap context */ 157fafd8bceSBlue Swirl switch ((demap_addr >> 4) & 3) { 158fafd8bceSBlue Swirl case 0: /* primary */ 159fafd8bceSBlue Swirl context = env1->dmmu.mmu_primary_context; 160fafd8bceSBlue Swirl break; 161fafd8bceSBlue Swirl case 1: /* secondary */ 162fafd8bceSBlue Swirl context = env1->dmmu.mmu_secondary_context; 163fafd8bceSBlue Swirl break; 164fafd8bceSBlue Swirl case 2: /* nucleus */ 165fafd8bceSBlue Swirl context = 0; 166fafd8bceSBlue Swirl break; 167fafd8bceSBlue Swirl case 3: /* reserved */ 168fafd8bceSBlue Swirl default: 169fafd8bceSBlue Swirl return; 170fafd8bceSBlue Swirl } 171fafd8bceSBlue Swirl 172fafd8bceSBlue Swirl for (i = 0; i < 64; i++) { 173fafd8bceSBlue Swirl if (TTE_IS_VALID(tlb[i].tte)) { 174fafd8bceSBlue Swirl 175fafd8bceSBlue Swirl if (is_demap_context) { 176fafd8bceSBlue Swirl /* will remove non-global entries matching context value */ 177fafd8bceSBlue Swirl if (TTE_IS_GLOBAL(tlb[i].tte) || 178fafd8bceSBlue Swirl !tlb_compare_context(&tlb[i], context)) { 179fafd8bceSBlue Swirl continue; 180fafd8bceSBlue Swirl } 181fafd8bceSBlue Swirl } else { 182fafd8bceSBlue Swirl /* demap page 183fafd8bceSBlue Swirl will remove any entry matching VA */ 184fafd8bceSBlue Swirl mask = 0xffffffffffffe000ULL; 185fafd8bceSBlue Swirl mask <<= 3 * ((tlb[i].tte >> 61) & 3); 186fafd8bceSBlue Swirl 187fafd8bceSBlue Swirl if (!compare_masked(demap_addr, tlb[i].tag, mask)) { 188fafd8bceSBlue Swirl continue; 189fafd8bceSBlue Swirl } 190fafd8bceSBlue Swirl 191fafd8bceSBlue Swirl /* entry should be global or matching context value */ 192fafd8bceSBlue Swirl if (!TTE_IS_GLOBAL(tlb[i].tte) && 193fafd8bceSBlue Swirl !tlb_compare_context(&tlb[i], context)) { 194fafd8bceSBlue Swirl continue; 195fafd8bceSBlue Swirl } 196fafd8bceSBlue Swirl } 197fafd8bceSBlue Swirl 198fafd8bceSBlue Swirl replace_tlb_entry(&tlb[i], 0, 0, env1); 199fafd8bceSBlue Swirl #ifdef DEBUG_MMU 200fafd8bceSBlue Swirl DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i); 201fafd8bceSBlue Swirl dump_mmu(stdout, fprintf, env1); 202fafd8bceSBlue Swirl #endif 203fafd8bceSBlue Swirl } 204fafd8bceSBlue Swirl } 205fafd8bceSBlue Swirl } 206fafd8bceSBlue Swirl 207fafd8bceSBlue Swirl static void replace_tlb_1bit_lru(SparcTLBEntry *tlb, 208fafd8bceSBlue Swirl uint64_t tlb_tag, uint64_t tlb_tte, 209c5f9864eSAndreas Färber const char *strmmu, CPUSPARCState *env1) 210fafd8bceSBlue Swirl { 211fafd8bceSBlue Swirl unsigned int i, replace_used; 212fafd8bceSBlue Swirl 21370f44d2fSArtyom Tarasenko if (cpu_has_hypervisor(env1)) { 21470f44d2fSArtyom Tarasenko uint64_t new_vaddr = tlb_tag & ~0x1fffULL; 21570f44d2fSArtyom Tarasenko uint64_t new_size = 8192ULL << 3 * TTE_PGSIZE(tlb_tte); 21670f44d2fSArtyom Tarasenko uint32_t new_ctx = tlb_tag & 0x1fffU; 21770f44d2fSArtyom Tarasenko for (i = 0; i < 64; i++) { 21870f44d2fSArtyom Tarasenko uint32_t ctx = tlb[i].tag & 0x1fffU; 21970f44d2fSArtyom Tarasenko /* check if new mapping overlaps an existing one */ 22070f44d2fSArtyom Tarasenko if (new_ctx == ctx) { 22170f44d2fSArtyom Tarasenko uint64_t vaddr = tlb[i].tag & ~0x1fffULL; 22270f44d2fSArtyom Tarasenko uint64_t size = 8192ULL << 3 * TTE_PGSIZE(tlb[i].tte); 22370f44d2fSArtyom Tarasenko if (new_vaddr == vaddr 22470f44d2fSArtyom Tarasenko || (new_vaddr < vaddr + size 22570f44d2fSArtyom Tarasenko && vaddr < new_vaddr + new_size)) { 22670f44d2fSArtyom Tarasenko DPRINTF_MMU("auto demap entry [%d] %lx->%lx\n", i, vaddr, 22770f44d2fSArtyom Tarasenko new_vaddr); 22870f44d2fSArtyom Tarasenko replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1); 22970f44d2fSArtyom Tarasenko return; 23070f44d2fSArtyom Tarasenko } 23170f44d2fSArtyom Tarasenko } 23270f44d2fSArtyom Tarasenko 23370f44d2fSArtyom Tarasenko } 23470f44d2fSArtyom Tarasenko } 235fafd8bceSBlue Swirl /* Try replacing invalid entry */ 236fafd8bceSBlue Swirl for (i = 0; i < 64; i++) { 237fafd8bceSBlue Swirl if (!TTE_IS_VALID(tlb[i].tte)) { 238fafd8bceSBlue Swirl replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1); 239fafd8bceSBlue Swirl #ifdef DEBUG_MMU 240fafd8bceSBlue Swirl DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i); 241fafd8bceSBlue Swirl dump_mmu(stdout, fprintf, env1); 242fafd8bceSBlue Swirl #endif 243fafd8bceSBlue Swirl return; 244fafd8bceSBlue Swirl } 245fafd8bceSBlue Swirl } 246fafd8bceSBlue Swirl 247fafd8bceSBlue Swirl /* All entries are valid, try replacing unlocked entry */ 248fafd8bceSBlue Swirl 249fafd8bceSBlue Swirl for (replace_used = 0; replace_used < 2; ++replace_used) { 250fafd8bceSBlue Swirl 251fafd8bceSBlue Swirl /* Used entries are not replaced on first pass */ 252fafd8bceSBlue Swirl 253fafd8bceSBlue Swirl for (i = 0; i < 64; i++) { 254fafd8bceSBlue Swirl if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) { 255fafd8bceSBlue Swirl 256fafd8bceSBlue Swirl replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1); 257fafd8bceSBlue Swirl #ifdef DEBUG_MMU 258fafd8bceSBlue Swirl DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n", 259fafd8bceSBlue Swirl strmmu, (replace_used ? "used" : "unused"), i); 260fafd8bceSBlue Swirl dump_mmu(stdout, fprintf, env1); 261fafd8bceSBlue Swirl #endif 262fafd8bceSBlue Swirl return; 263fafd8bceSBlue Swirl } 264fafd8bceSBlue Swirl } 265fafd8bceSBlue Swirl 266fafd8bceSBlue Swirl /* Now reset used bit and search for unused entries again */ 267fafd8bceSBlue Swirl 268fafd8bceSBlue Swirl for (i = 0; i < 64; i++) { 269fafd8bceSBlue Swirl TTE_SET_UNUSED(tlb[i].tte); 270fafd8bceSBlue Swirl } 271fafd8bceSBlue Swirl } 272fafd8bceSBlue Swirl 273fafd8bceSBlue Swirl #ifdef DEBUG_MMU 2744797a685SArtyom Tarasenko DPRINTF_MMU("%s lru replacement: no free entries available, " 2754797a685SArtyom Tarasenko "replacing the last one\n", strmmu); 276fafd8bceSBlue Swirl #endif 2774797a685SArtyom Tarasenko /* corner case: the last entry is replaced anyway */ 2784797a685SArtyom Tarasenko replace_tlb_entry(&tlb[63], tlb_tag, tlb_tte, env1); 279fafd8bceSBlue Swirl } 280fafd8bceSBlue Swirl 281fafd8bceSBlue Swirl #endif 282fafd8bceSBlue Swirl 28369694625SPeter Maydell #ifdef TARGET_SPARC64 284fafd8bceSBlue Swirl /* returns true if access using this ASI is to have address translated by MMU 285fafd8bceSBlue Swirl otherwise access is to raw physical address */ 28669694625SPeter Maydell /* TODO: check sparc32 bits */ 287fafd8bceSBlue Swirl static inline int is_translating_asi(int asi) 288fafd8bceSBlue Swirl { 289fafd8bceSBlue Swirl /* Ultrasparc IIi translating asi 290fafd8bceSBlue Swirl - note this list is defined by cpu implementation 291fafd8bceSBlue Swirl */ 292fafd8bceSBlue Swirl switch (asi) { 293fafd8bceSBlue Swirl case 0x04 ... 0x11: 294fafd8bceSBlue Swirl case 0x16 ... 0x19: 295fafd8bceSBlue Swirl case 0x1E ... 0x1F: 296fafd8bceSBlue Swirl case 0x24 ... 0x2C: 297fafd8bceSBlue Swirl case 0x70 ... 0x73: 298fafd8bceSBlue Swirl case 0x78 ... 0x79: 299fafd8bceSBlue Swirl case 0x80 ... 0xFF: 300fafd8bceSBlue Swirl return 1; 301fafd8bceSBlue Swirl 302fafd8bceSBlue Swirl default: 303fafd8bceSBlue Swirl return 0; 304fafd8bceSBlue Swirl } 305fafd8bceSBlue Swirl } 306fafd8bceSBlue Swirl 307f939ffe5SRichard Henderson static inline target_ulong address_mask(CPUSPARCState *env1, target_ulong addr) 308f939ffe5SRichard Henderson { 309f939ffe5SRichard Henderson if (AM_CHECK(env1)) { 310f939ffe5SRichard Henderson addr &= 0xffffffffULL; 311f939ffe5SRichard Henderson } 312f939ffe5SRichard Henderson return addr; 313f939ffe5SRichard Henderson } 314f939ffe5SRichard Henderson 315fe8d8f0fSBlue Swirl static inline target_ulong asi_address_mask(CPUSPARCState *env, 316fafd8bceSBlue Swirl int asi, target_ulong addr) 317fafd8bceSBlue Swirl { 318fafd8bceSBlue Swirl if (is_translating_asi(asi)) { 319f939ffe5SRichard Henderson addr = address_mask(env, addr); 320fafd8bceSBlue Swirl } 321f939ffe5SRichard Henderson return addr; 322fafd8bceSBlue Swirl } 3237cd39ef2SArtyom Tarasenko 3247cd39ef2SArtyom Tarasenko #ifndef CONFIG_USER_ONLY 3257cd39ef2SArtyom Tarasenko static inline void do_check_asi(CPUSPARCState *env, int asi, uintptr_t ra) 3267cd39ef2SArtyom Tarasenko { 3277cd39ef2SArtyom Tarasenko /* ASIs >= 0x80 are user mode. 3287cd39ef2SArtyom Tarasenko * ASIs >= 0x30 are hyper mode (or super if hyper is not available). 3297cd39ef2SArtyom Tarasenko * ASIs <= 0x2f are super mode. 3307cd39ef2SArtyom Tarasenko */ 3317cd39ef2SArtyom Tarasenko if (asi < 0x80 3327cd39ef2SArtyom Tarasenko && !cpu_hypervisor_mode(env) 3337cd39ef2SArtyom Tarasenko && (!cpu_supervisor_mode(env) 3347cd39ef2SArtyom Tarasenko || (asi >= 0x30 && cpu_has_hypervisor(env)))) { 3357cd39ef2SArtyom Tarasenko cpu_raise_exception_ra(env, TT_PRIV_ACT, ra); 3367cd39ef2SArtyom Tarasenko } 3377cd39ef2SArtyom Tarasenko } 3387cd39ef2SArtyom Tarasenko #endif /* !CONFIG_USER_ONLY */ 339e60538c7SPeter Maydell #endif 340fafd8bceSBlue Swirl 3412f9d35fcSRichard Henderson static void do_check_align(CPUSPARCState *env, target_ulong addr, 3422f9d35fcSRichard Henderson uint32_t align, uintptr_t ra) 343fafd8bceSBlue Swirl { 344fafd8bceSBlue Swirl if (addr & align) { 345fafd8bceSBlue Swirl #ifdef DEBUG_UNALIGNED 346fafd8bceSBlue Swirl printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx 347fafd8bceSBlue Swirl "\n", addr, env->pc); 348fafd8bceSBlue Swirl #endif 3492f9d35fcSRichard Henderson cpu_raise_exception_ra(env, TT_UNALIGNED, ra); 350fafd8bceSBlue Swirl } 351fafd8bceSBlue Swirl } 352fafd8bceSBlue Swirl 3532f9d35fcSRichard Henderson void helper_check_align(CPUSPARCState *env, target_ulong addr, uint32_t align) 3542f9d35fcSRichard Henderson { 3552f9d35fcSRichard Henderson do_check_align(env, addr, align, GETPC()); 3562f9d35fcSRichard Henderson } 3572f9d35fcSRichard Henderson 358fafd8bceSBlue Swirl #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \ 359fafd8bceSBlue Swirl defined(DEBUG_MXCC) 360c5f9864eSAndreas Färber static void dump_mxcc(CPUSPARCState *env) 361fafd8bceSBlue Swirl { 362fafd8bceSBlue Swirl printf("mxccdata: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 363fafd8bceSBlue Swirl "\n", 364fafd8bceSBlue Swirl env->mxccdata[0], env->mxccdata[1], 365fafd8bceSBlue Swirl env->mxccdata[2], env->mxccdata[3]); 366fafd8bceSBlue Swirl printf("mxccregs: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 367fafd8bceSBlue Swirl "\n" 368fafd8bceSBlue Swirl " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 369fafd8bceSBlue Swirl "\n", 370fafd8bceSBlue Swirl env->mxccregs[0], env->mxccregs[1], 371fafd8bceSBlue Swirl env->mxccregs[2], env->mxccregs[3], 372fafd8bceSBlue Swirl env->mxccregs[4], env->mxccregs[5], 373fafd8bceSBlue Swirl env->mxccregs[6], env->mxccregs[7]); 374fafd8bceSBlue Swirl } 375fafd8bceSBlue Swirl #endif 376fafd8bceSBlue Swirl 377fafd8bceSBlue Swirl #if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \ 378fafd8bceSBlue Swirl && defined(DEBUG_ASI) 379fafd8bceSBlue Swirl static void dump_asi(const char *txt, target_ulong addr, int asi, int size, 380fafd8bceSBlue Swirl uint64_t r1) 381fafd8bceSBlue Swirl { 382fafd8bceSBlue Swirl switch (size) { 383fafd8bceSBlue Swirl case 1: 384fafd8bceSBlue Swirl DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt, 385fafd8bceSBlue Swirl addr, asi, r1 & 0xff); 386fafd8bceSBlue Swirl break; 387fafd8bceSBlue Swirl case 2: 388fafd8bceSBlue Swirl DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt, 389fafd8bceSBlue Swirl addr, asi, r1 & 0xffff); 390fafd8bceSBlue Swirl break; 391fafd8bceSBlue Swirl case 4: 392fafd8bceSBlue Swirl DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt, 393fafd8bceSBlue Swirl addr, asi, r1 & 0xffffffff); 394fafd8bceSBlue Swirl break; 395fafd8bceSBlue Swirl case 8: 396fafd8bceSBlue Swirl DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt, 397fafd8bceSBlue Swirl addr, asi, r1); 398fafd8bceSBlue Swirl break; 399fafd8bceSBlue Swirl } 400fafd8bceSBlue Swirl } 401fafd8bceSBlue Swirl #endif 402fafd8bceSBlue Swirl 403fafd8bceSBlue Swirl #ifndef TARGET_SPARC64 404fafd8bceSBlue Swirl #ifndef CONFIG_USER_ONLY 405fafd8bceSBlue Swirl 406fafd8bceSBlue Swirl 407fafd8bceSBlue Swirl /* Leon3 cache control */ 408fafd8bceSBlue Swirl 409fe8d8f0fSBlue Swirl static void leon3_cache_control_st(CPUSPARCState *env, target_ulong addr, 410fe8d8f0fSBlue Swirl uint64_t val, int size) 411fafd8bceSBlue Swirl { 412fafd8bceSBlue Swirl DPRINTF_CACHE_CONTROL("st addr:%08x, val:%" PRIx64 ", size:%d\n", 413fafd8bceSBlue Swirl addr, val, size); 414fafd8bceSBlue Swirl 415fafd8bceSBlue Swirl if (size != 4) { 416fafd8bceSBlue Swirl DPRINTF_CACHE_CONTROL("32bits only\n"); 417fafd8bceSBlue Swirl return; 418fafd8bceSBlue Swirl } 419fafd8bceSBlue Swirl 420fafd8bceSBlue Swirl switch (addr) { 421fafd8bceSBlue Swirl case 0x00: /* Cache control */ 422fafd8bceSBlue Swirl 423fafd8bceSBlue Swirl /* These values must always be read as zeros */ 424fafd8bceSBlue Swirl val &= ~CACHE_CTRL_FD; 425fafd8bceSBlue Swirl val &= ~CACHE_CTRL_FI; 426fafd8bceSBlue Swirl val &= ~CACHE_CTRL_IB; 427fafd8bceSBlue Swirl val &= ~CACHE_CTRL_IP; 428fafd8bceSBlue Swirl val &= ~CACHE_CTRL_DP; 429fafd8bceSBlue Swirl 430fafd8bceSBlue Swirl env->cache_control = val; 431fafd8bceSBlue Swirl break; 432fafd8bceSBlue Swirl case 0x04: /* Instruction cache configuration */ 433fafd8bceSBlue Swirl case 0x08: /* Data cache configuration */ 434fafd8bceSBlue Swirl /* Read Only */ 435fafd8bceSBlue Swirl break; 436fafd8bceSBlue Swirl default: 437fafd8bceSBlue Swirl DPRINTF_CACHE_CONTROL("write unknown register %08x\n", addr); 438fafd8bceSBlue Swirl break; 439fafd8bceSBlue Swirl }; 440fafd8bceSBlue Swirl } 441fafd8bceSBlue Swirl 442fe8d8f0fSBlue Swirl static uint64_t leon3_cache_control_ld(CPUSPARCState *env, target_ulong addr, 443fe8d8f0fSBlue Swirl int size) 444fafd8bceSBlue Swirl { 445fafd8bceSBlue Swirl uint64_t ret = 0; 446fafd8bceSBlue Swirl 447fafd8bceSBlue Swirl if (size != 4) { 448fafd8bceSBlue Swirl DPRINTF_CACHE_CONTROL("32bits only\n"); 449fafd8bceSBlue Swirl return 0; 450fafd8bceSBlue Swirl } 451fafd8bceSBlue Swirl 452fafd8bceSBlue Swirl switch (addr) { 453fafd8bceSBlue Swirl case 0x00: /* Cache control */ 454fafd8bceSBlue Swirl ret = env->cache_control; 455fafd8bceSBlue Swirl break; 456fafd8bceSBlue Swirl 457fafd8bceSBlue Swirl /* Configuration registers are read and only always keep those 458fafd8bceSBlue Swirl predefined values */ 459fafd8bceSBlue Swirl 460fafd8bceSBlue Swirl case 0x04: /* Instruction cache configuration */ 461fafd8bceSBlue Swirl ret = 0x10220000; 462fafd8bceSBlue Swirl break; 463fafd8bceSBlue Swirl case 0x08: /* Data cache configuration */ 464fafd8bceSBlue Swirl ret = 0x18220000; 465fafd8bceSBlue Swirl break; 466fafd8bceSBlue Swirl default: 467fafd8bceSBlue Swirl DPRINTF_CACHE_CONTROL("read unknown register %08x\n", addr); 468fafd8bceSBlue Swirl break; 469fafd8bceSBlue Swirl }; 470fafd8bceSBlue Swirl DPRINTF_CACHE_CONTROL("ld addr:%08x, ret:0x%" PRIx64 ", size:%d\n", 471fafd8bceSBlue Swirl addr, ret, size); 472fafd8bceSBlue Swirl return ret; 473fafd8bceSBlue Swirl } 474fafd8bceSBlue Swirl 4756850811eSRichard Henderson uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, 4766850811eSRichard Henderson int asi, uint32_t memop) 477fafd8bceSBlue Swirl { 4786850811eSRichard Henderson int size = 1 << (memop & MO_SIZE); 4796850811eSRichard Henderson int sign = memop & MO_SIGN; 4802fad1112SAndreas Färber CPUState *cs = CPU(sparc_env_get_cpu(env)); 481fafd8bceSBlue Swirl uint64_t ret = 0; 482fafd8bceSBlue Swirl #if defined(DEBUG_MXCC) || defined(DEBUG_ASI) 483fafd8bceSBlue Swirl uint32_t last_addr = addr; 484fafd8bceSBlue Swirl #endif 485fafd8bceSBlue Swirl 4862f9d35fcSRichard Henderson do_check_align(env, addr, size - 1, GETPC()); 487fafd8bceSBlue Swirl switch (asi) { 4880cc1f4bfSRichard Henderson case ASI_M_MXCC: /* SuperSparc MXCC registers, or... */ 4890cc1f4bfSRichard Henderson /* case ASI_LEON_CACHEREGS: Leon3 cache control */ 490fafd8bceSBlue Swirl switch (addr) { 491fafd8bceSBlue Swirl case 0x00: /* Leon3 Cache Control */ 492fafd8bceSBlue Swirl case 0x08: /* Leon3 Instruction Cache config */ 493fafd8bceSBlue Swirl case 0x0C: /* Leon3 Date Cache config */ 494fafd8bceSBlue Swirl if (env->def->features & CPU_FEATURE_CACHE_CTRL) { 495fe8d8f0fSBlue Swirl ret = leon3_cache_control_ld(env, addr, size); 496fafd8bceSBlue Swirl } 497fafd8bceSBlue Swirl break; 498fafd8bceSBlue Swirl case 0x01c00a00: /* MXCC control register */ 499fafd8bceSBlue Swirl if (size == 8) { 500fafd8bceSBlue Swirl ret = env->mxccregs[3]; 501fafd8bceSBlue Swirl } else { 50271547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 50371547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 504fafd8bceSBlue Swirl size); 505fafd8bceSBlue Swirl } 506fafd8bceSBlue Swirl break; 507fafd8bceSBlue Swirl case 0x01c00a04: /* MXCC control register */ 508fafd8bceSBlue Swirl if (size == 4) { 509fafd8bceSBlue Swirl ret = env->mxccregs[3]; 510fafd8bceSBlue Swirl } else { 51171547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 51271547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 513fafd8bceSBlue Swirl size); 514fafd8bceSBlue Swirl } 515fafd8bceSBlue Swirl break; 516fafd8bceSBlue Swirl case 0x01c00c00: /* Module reset register */ 517fafd8bceSBlue Swirl if (size == 8) { 518fafd8bceSBlue Swirl ret = env->mxccregs[5]; 519fafd8bceSBlue Swirl /* should we do something here? */ 520fafd8bceSBlue Swirl } else { 52171547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 52271547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 523fafd8bceSBlue Swirl size); 524fafd8bceSBlue Swirl } 525fafd8bceSBlue Swirl break; 526fafd8bceSBlue Swirl case 0x01c00f00: /* MBus port address register */ 527fafd8bceSBlue Swirl if (size == 8) { 528fafd8bceSBlue Swirl ret = env->mxccregs[7]; 529fafd8bceSBlue Swirl } else { 53071547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 53171547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 532fafd8bceSBlue Swirl size); 533fafd8bceSBlue Swirl } 534fafd8bceSBlue Swirl break; 535fafd8bceSBlue Swirl default: 53671547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 53771547a3bSBlue Swirl "%08x: unimplemented address, size: %d\n", addr, 538fafd8bceSBlue Swirl size); 539fafd8bceSBlue Swirl break; 540fafd8bceSBlue Swirl } 541fafd8bceSBlue Swirl DPRINTF_MXCC("asi = %d, size = %d, sign = %d, " 542fafd8bceSBlue Swirl "addr = %08x -> ret = %" PRIx64 "," 543fafd8bceSBlue Swirl "addr = %08x\n", asi, size, sign, last_addr, ret, addr); 544fafd8bceSBlue Swirl #ifdef DEBUG_MXCC 545fafd8bceSBlue Swirl dump_mxcc(env); 546fafd8bceSBlue Swirl #endif 547fafd8bceSBlue Swirl break; 5480cc1f4bfSRichard Henderson case ASI_M_FLUSH_PROBE: /* SuperSparc MMU probe */ 5490cc1f4bfSRichard Henderson case ASI_LEON_MMUFLUSH: /* LEON3 MMU probe */ 550fafd8bceSBlue Swirl { 551fafd8bceSBlue Swirl int mmulev; 552fafd8bceSBlue Swirl 553fafd8bceSBlue Swirl mmulev = (addr >> 8) & 15; 554fafd8bceSBlue Swirl if (mmulev > 4) { 555fafd8bceSBlue Swirl ret = 0; 556fafd8bceSBlue Swirl } else { 557fafd8bceSBlue Swirl ret = mmu_probe(env, addr, mmulev); 558fafd8bceSBlue Swirl } 559fafd8bceSBlue Swirl DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n", 560fafd8bceSBlue Swirl addr, mmulev, ret); 561fafd8bceSBlue Swirl } 562fafd8bceSBlue Swirl break; 5630cc1f4bfSRichard Henderson case ASI_M_MMUREGS: /* SuperSparc MMU regs */ 5640cc1f4bfSRichard Henderson case ASI_LEON_MMUREGS: /* LEON3 MMU regs */ 565fafd8bceSBlue Swirl { 566fafd8bceSBlue Swirl int reg = (addr >> 8) & 0x1f; 567fafd8bceSBlue Swirl 568fafd8bceSBlue Swirl ret = env->mmuregs[reg]; 569fafd8bceSBlue Swirl if (reg == 3) { /* Fault status cleared on read */ 570fafd8bceSBlue Swirl env->mmuregs[3] = 0; 571fafd8bceSBlue Swirl } else if (reg == 0x13) { /* Fault status read */ 572fafd8bceSBlue Swirl ret = env->mmuregs[3]; 573fafd8bceSBlue Swirl } else if (reg == 0x14) { /* Fault address read */ 574fafd8bceSBlue Swirl ret = env->mmuregs[4]; 575fafd8bceSBlue Swirl } 576fafd8bceSBlue Swirl DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret); 577fafd8bceSBlue Swirl } 578fafd8bceSBlue Swirl break; 5790cc1f4bfSRichard Henderson case ASI_M_TLBDIAG: /* Turbosparc ITLB Diagnostic */ 5800cc1f4bfSRichard Henderson case ASI_M_DIAGS: /* Turbosparc DTLB Diagnostic */ 5810cc1f4bfSRichard Henderson case ASI_M_IODIAG: /* Turbosparc IOTLB Diagnostic */ 582fafd8bceSBlue Swirl break; 5830cc1f4bfSRichard Henderson case ASI_KERNELTXT: /* Supervisor code access */ 584fafd8bceSBlue Swirl switch (size) { 585fafd8bceSBlue Swirl case 1: 5860184e266SBlue Swirl ret = cpu_ldub_code(env, addr); 587fafd8bceSBlue Swirl break; 588fafd8bceSBlue Swirl case 2: 5890184e266SBlue Swirl ret = cpu_lduw_code(env, addr); 590fafd8bceSBlue Swirl break; 591fafd8bceSBlue Swirl default: 592fafd8bceSBlue Swirl case 4: 5930184e266SBlue Swirl ret = cpu_ldl_code(env, addr); 594fafd8bceSBlue Swirl break; 595fafd8bceSBlue Swirl case 8: 5960184e266SBlue Swirl ret = cpu_ldq_code(env, addr); 597fafd8bceSBlue Swirl break; 598fafd8bceSBlue Swirl } 599fafd8bceSBlue Swirl break; 6000cc1f4bfSRichard Henderson case ASI_M_TXTC_TAG: /* SparcStation 5 I-cache tag */ 6010cc1f4bfSRichard Henderson case ASI_M_TXTC_DATA: /* SparcStation 5 I-cache data */ 6020cc1f4bfSRichard Henderson case ASI_M_DATAC_TAG: /* SparcStation 5 D-cache tag */ 6030cc1f4bfSRichard Henderson case ASI_M_DATAC_DATA: /* SparcStation 5 D-cache data */ 604fafd8bceSBlue Swirl break; 605fafd8bceSBlue Swirl case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ 606fafd8bceSBlue Swirl switch (size) { 607fafd8bceSBlue Swirl case 1: 6082c17449bSEdgar E. Iglesias ret = ldub_phys(cs->as, (hwaddr)addr 609a8170e5eSAvi Kivity | ((hwaddr)(asi & 0xf) << 32)); 610fafd8bceSBlue Swirl break; 611fafd8bceSBlue Swirl case 2: 61241701aa4SEdgar E. Iglesias ret = lduw_phys(cs->as, (hwaddr)addr 613a8170e5eSAvi Kivity | ((hwaddr)(asi & 0xf) << 32)); 614fafd8bceSBlue Swirl break; 615fafd8bceSBlue Swirl default: 616fafd8bceSBlue Swirl case 4: 617fdfba1a2SEdgar E. Iglesias ret = ldl_phys(cs->as, (hwaddr)addr 618a8170e5eSAvi Kivity | ((hwaddr)(asi & 0xf) << 32)); 619fafd8bceSBlue Swirl break; 620fafd8bceSBlue Swirl case 8: 6212c17449bSEdgar E. Iglesias ret = ldq_phys(cs->as, (hwaddr)addr 622a8170e5eSAvi Kivity | ((hwaddr)(asi & 0xf) << 32)); 623fafd8bceSBlue Swirl break; 624fafd8bceSBlue Swirl } 625fafd8bceSBlue Swirl break; 626fafd8bceSBlue Swirl case 0x30: /* Turbosparc secondary cache diagnostic */ 627fafd8bceSBlue Swirl case 0x31: /* Turbosparc RAM snoop */ 628fafd8bceSBlue Swirl case 0x32: /* Turbosparc page table descriptor diagnostic */ 629fafd8bceSBlue Swirl case 0x39: /* data cache diagnostic register */ 630fafd8bceSBlue Swirl ret = 0; 631fafd8bceSBlue Swirl break; 632fafd8bceSBlue Swirl case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */ 633fafd8bceSBlue Swirl { 634fafd8bceSBlue Swirl int reg = (addr >> 8) & 3; 635fafd8bceSBlue Swirl 636fafd8bceSBlue Swirl switch (reg) { 637fafd8bceSBlue Swirl case 0: /* Breakpoint Value (Addr) */ 638fafd8bceSBlue Swirl ret = env->mmubpregs[reg]; 639fafd8bceSBlue Swirl break; 640fafd8bceSBlue Swirl case 1: /* Breakpoint Mask */ 641fafd8bceSBlue Swirl ret = env->mmubpregs[reg]; 642fafd8bceSBlue Swirl break; 643fafd8bceSBlue Swirl case 2: /* Breakpoint Control */ 644fafd8bceSBlue Swirl ret = env->mmubpregs[reg]; 645fafd8bceSBlue Swirl break; 646fafd8bceSBlue Swirl case 3: /* Breakpoint Status */ 647fafd8bceSBlue Swirl ret = env->mmubpregs[reg]; 648fafd8bceSBlue Swirl env->mmubpregs[reg] = 0ULL; 649fafd8bceSBlue Swirl break; 650fafd8bceSBlue Swirl } 651fafd8bceSBlue Swirl DPRINTF_MMU("read breakpoint reg[%d] 0x%016" PRIx64 "\n", reg, 652fafd8bceSBlue Swirl ret); 653fafd8bceSBlue Swirl } 654fafd8bceSBlue Swirl break; 655fafd8bceSBlue Swirl case 0x49: /* SuperSPARC MMU Counter Breakpoint Value */ 656fafd8bceSBlue Swirl ret = env->mmubpctrv; 657fafd8bceSBlue Swirl break; 658fafd8bceSBlue Swirl case 0x4a: /* SuperSPARC MMU Counter Breakpoint Control */ 659fafd8bceSBlue Swirl ret = env->mmubpctrc; 660fafd8bceSBlue Swirl break; 661fafd8bceSBlue Swirl case 0x4b: /* SuperSPARC MMU Counter Breakpoint Status */ 662fafd8bceSBlue Swirl ret = env->mmubpctrs; 663fafd8bceSBlue Swirl break; 664fafd8bceSBlue Swirl case 0x4c: /* SuperSPARC MMU Breakpoint Action */ 665fafd8bceSBlue Swirl ret = env->mmubpaction; 666fafd8bceSBlue Swirl break; 6670cc1f4bfSRichard Henderson case ASI_USERTXT: /* User code access, XXX */ 668fafd8bceSBlue Swirl default: 6692fad1112SAndreas Färber cpu_unassigned_access(cs, addr, false, false, asi, size); 670fafd8bceSBlue Swirl ret = 0; 671fafd8bceSBlue Swirl break; 672918d9a2cSRichard Henderson 673918d9a2cSRichard Henderson case ASI_USERDATA: /* User data access */ 674918d9a2cSRichard Henderson case ASI_KERNELDATA: /* Supervisor data access */ 675918d9a2cSRichard Henderson case ASI_P: /* Implicit primary context data access (v9 only?) */ 676918d9a2cSRichard Henderson case ASI_M_BYPASS: /* MMU passthrough */ 677918d9a2cSRichard Henderson case ASI_LEON_BYPASS: /* LEON MMU passthrough */ 678918d9a2cSRichard Henderson /* These are always handled inline. */ 679918d9a2cSRichard Henderson g_assert_not_reached(); 680fafd8bceSBlue Swirl } 681fafd8bceSBlue Swirl if (sign) { 682fafd8bceSBlue Swirl switch (size) { 683fafd8bceSBlue Swirl case 1: 684fafd8bceSBlue Swirl ret = (int8_t) ret; 685fafd8bceSBlue Swirl break; 686fafd8bceSBlue Swirl case 2: 687fafd8bceSBlue Swirl ret = (int16_t) ret; 688fafd8bceSBlue Swirl break; 689fafd8bceSBlue Swirl case 4: 690fafd8bceSBlue Swirl ret = (int32_t) ret; 691fafd8bceSBlue Swirl break; 692fafd8bceSBlue Swirl default: 693fafd8bceSBlue Swirl break; 694fafd8bceSBlue Swirl } 695fafd8bceSBlue Swirl } 696fafd8bceSBlue Swirl #ifdef DEBUG_ASI 697fafd8bceSBlue Swirl dump_asi("read ", last_addr, asi, size, ret); 698fafd8bceSBlue Swirl #endif 699fafd8bceSBlue Swirl return ret; 700fafd8bceSBlue Swirl } 701fafd8bceSBlue Swirl 7026850811eSRichard Henderson void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, 7036850811eSRichard Henderson int asi, uint32_t memop) 704fafd8bceSBlue Swirl { 7056850811eSRichard Henderson int size = 1 << (memop & MO_SIZE); 70631b030d4SAndreas Färber SPARCCPU *cpu = sparc_env_get_cpu(env); 70731b030d4SAndreas Färber CPUState *cs = CPU(cpu); 70831b030d4SAndreas Färber 7092f9d35fcSRichard Henderson do_check_align(env, addr, size - 1, GETPC()); 710fafd8bceSBlue Swirl switch (asi) { 7110cc1f4bfSRichard Henderson case ASI_M_MXCC: /* SuperSparc MXCC registers, or... */ 7120cc1f4bfSRichard Henderson /* case ASI_LEON_CACHEREGS: Leon3 cache control */ 713fafd8bceSBlue Swirl switch (addr) { 714fafd8bceSBlue Swirl case 0x00: /* Leon3 Cache Control */ 715fafd8bceSBlue Swirl case 0x08: /* Leon3 Instruction Cache config */ 716fafd8bceSBlue Swirl case 0x0C: /* Leon3 Date Cache config */ 717fafd8bceSBlue Swirl if (env->def->features & CPU_FEATURE_CACHE_CTRL) { 718fe8d8f0fSBlue Swirl leon3_cache_control_st(env, addr, val, size); 719fafd8bceSBlue Swirl } 720fafd8bceSBlue Swirl break; 721fafd8bceSBlue Swirl 722fafd8bceSBlue Swirl case 0x01c00000: /* MXCC stream data register 0 */ 723fafd8bceSBlue Swirl if (size == 8) { 724fafd8bceSBlue Swirl env->mxccdata[0] = val; 725fafd8bceSBlue Swirl } else { 72671547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 72771547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 728fafd8bceSBlue Swirl size); 729fafd8bceSBlue Swirl } 730fafd8bceSBlue Swirl break; 731fafd8bceSBlue Swirl case 0x01c00008: /* MXCC stream data register 1 */ 732fafd8bceSBlue Swirl if (size == 8) { 733fafd8bceSBlue Swirl env->mxccdata[1] = val; 734fafd8bceSBlue Swirl } else { 73571547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 73671547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 737fafd8bceSBlue Swirl size); 738fafd8bceSBlue Swirl } 739fafd8bceSBlue Swirl break; 740fafd8bceSBlue Swirl case 0x01c00010: /* MXCC stream data register 2 */ 741fafd8bceSBlue Swirl if (size == 8) { 742fafd8bceSBlue Swirl env->mxccdata[2] = val; 743fafd8bceSBlue Swirl } else { 74471547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 74571547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 746fafd8bceSBlue Swirl size); 747fafd8bceSBlue Swirl } 748fafd8bceSBlue Swirl break; 749fafd8bceSBlue Swirl case 0x01c00018: /* MXCC stream data register 3 */ 750fafd8bceSBlue Swirl if (size == 8) { 751fafd8bceSBlue Swirl env->mxccdata[3] = val; 752fafd8bceSBlue Swirl } else { 75371547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 75471547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 755fafd8bceSBlue Swirl size); 756fafd8bceSBlue Swirl } 757fafd8bceSBlue Swirl break; 758fafd8bceSBlue Swirl case 0x01c00100: /* MXCC stream source */ 759fafd8bceSBlue Swirl if (size == 8) { 760fafd8bceSBlue Swirl env->mxccregs[0] = val; 761fafd8bceSBlue Swirl } else { 76271547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 76371547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 764fafd8bceSBlue Swirl size); 765fafd8bceSBlue Swirl } 7662c17449bSEdgar E. Iglesias env->mxccdata[0] = ldq_phys(cs->as, 7672c17449bSEdgar E. Iglesias (env->mxccregs[0] & 0xffffffffULL) + 768fafd8bceSBlue Swirl 0); 7692c17449bSEdgar E. Iglesias env->mxccdata[1] = ldq_phys(cs->as, 7702c17449bSEdgar E. Iglesias (env->mxccregs[0] & 0xffffffffULL) + 771fafd8bceSBlue Swirl 8); 7722c17449bSEdgar E. Iglesias env->mxccdata[2] = ldq_phys(cs->as, 7732c17449bSEdgar E. Iglesias (env->mxccregs[0] & 0xffffffffULL) + 774fafd8bceSBlue Swirl 16); 7752c17449bSEdgar E. Iglesias env->mxccdata[3] = ldq_phys(cs->as, 7762c17449bSEdgar E. Iglesias (env->mxccregs[0] & 0xffffffffULL) + 777fafd8bceSBlue Swirl 24); 778fafd8bceSBlue Swirl break; 779fafd8bceSBlue Swirl case 0x01c00200: /* MXCC stream destination */ 780fafd8bceSBlue Swirl if (size == 8) { 781fafd8bceSBlue Swirl env->mxccregs[1] = val; 782fafd8bceSBlue Swirl } else { 78371547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 78471547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 785fafd8bceSBlue Swirl size); 786fafd8bceSBlue Swirl } 787f606604fSEdgar E. Iglesias stq_phys(cs->as, (env->mxccregs[1] & 0xffffffffULL) + 0, 788fafd8bceSBlue Swirl env->mxccdata[0]); 789f606604fSEdgar E. Iglesias stq_phys(cs->as, (env->mxccregs[1] & 0xffffffffULL) + 8, 790fafd8bceSBlue Swirl env->mxccdata[1]); 791f606604fSEdgar E. Iglesias stq_phys(cs->as, (env->mxccregs[1] & 0xffffffffULL) + 16, 792fafd8bceSBlue Swirl env->mxccdata[2]); 793f606604fSEdgar E. Iglesias stq_phys(cs->as, (env->mxccregs[1] & 0xffffffffULL) + 24, 794fafd8bceSBlue Swirl env->mxccdata[3]); 795fafd8bceSBlue Swirl break; 796fafd8bceSBlue Swirl case 0x01c00a00: /* MXCC control register */ 797fafd8bceSBlue Swirl if (size == 8) { 798fafd8bceSBlue Swirl env->mxccregs[3] = val; 799fafd8bceSBlue Swirl } else { 80071547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 80171547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 802fafd8bceSBlue Swirl size); 803fafd8bceSBlue Swirl } 804fafd8bceSBlue Swirl break; 805fafd8bceSBlue Swirl case 0x01c00a04: /* MXCC control register */ 806fafd8bceSBlue Swirl if (size == 4) { 807fafd8bceSBlue Swirl env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL) 808fafd8bceSBlue Swirl | val; 809fafd8bceSBlue Swirl } else { 81071547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 81171547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 812fafd8bceSBlue Swirl size); 813fafd8bceSBlue Swirl } 814fafd8bceSBlue Swirl break; 815fafd8bceSBlue Swirl case 0x01c00e00: /* MXCC error register */ 816fafd8bceSBlue Swirl /* writing a 1 bit clears the error */ 817fafd8bceSBlue Swirl if (size == 8) { 818fafd8bceSBlue Swirl env->mxccregs[6] &= ~val; 819fafd8bceSBlue Swirl } else { 82071547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 82171547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 822fafd8bceSBlue Swirl size); 823fafd8bceSBlue Swirl } 824fafd8bceSBlue Swirl break; 825fafd8bceSBlue Swirl case 0x01c00f00: /* MBus port address register */ 826fafd8bceSBlue Swirl if (size == 8) { 827fafd8bceSBlue Swirl env->mxccregs[7] = val; 828fafd8bceSBlue Swirl } else { 82971547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 83071547a3bSBlue Swirl "%08x: unimplemented access size: %d\n", addr, 831fafd8bceSBlue Swirl size); 832fafd8bceSBlue Swirl } 833fafd8bceSBlue Swirl break; 834fafd8bceSBlue Swirl default: 83571547a3bSBlue Swirl qemu_log_mask(LOG_UNIMP, 83671547a3bSBlue Swirl "%08x: unimplemented address, size: %d\n", addr, 837fafd8bceSBlue Swirl size); 838fafd8bceSBlue Swirl break; 839fafd8bceSBlue Swirl } 840fafd8bceSBlue Swirl DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n", 841fafd8bceSBlue Swirl asi, size, addr, val); 842fafd8bceSBlue Swirl #ifdef DEBUG_MXCC 843fafd8bceSBlue Swirl dump_mxcc(env); 844fafd8bceSBlue Swirl #endif 845fafd8bceSBlue Swirl break; 8460cc1f4bfSRichard Henderson case ASI_M_FLUSH_PROBE: /* SuperSparc MMU flush */ 8470cc1f4bfSRichard Henderson case ASI_LEON_MMUFLUSH: /* LEON3 MMU flush */ 848fafd8bceSBlue Swirl { 849fafd8bceSBlue Swirl int mmulev; 850fafd8bceSBlue Swirl 851fafd8bceSBlue Swirl mmulev = (addr >> 8) & 15; 852fafd8bceSBlue Swirl DPRINTF_MMU("mmu flush level %d\n", mmulev); 853fafd8bceSBlue Swirl switch (mmulev) { 854fafd8bceSBlue Swirl case 0: /* flush page */ 85531b030d4SAndreas Färber tlb_flush_page(CPU(cpu), addr & 0xfffff000); 856fafd8bceSBlue Swirl break; 857fafd8bceSBlue Swirl case 1: /* flush segment (256k) */ 858fafd8bceSBlue Swirl case 2: /* flush region (16M) */ 859fafd8bceSBlue Swirl case 3: /* flush context (4G) */ 860fafd8bceSBlue Swirl case 4: /* flush entire */ 861d10eb08fSAlex Bennée tlb_flush(CPU(cpu)); 862fafd8bceSBlue Swirl break; 863fafd8bceSBlue Swirl default: 864fafd8bceSBlue Swirl break; 865fafd8bceSBlue Swirl } 866fafd8bceSBlue Swirl #ifdef DEBUG_MMU 867fafd8bceSBlue Swirl dump_mmu(stdout, fprintf, env); 868fafd8bceSBlue Swirl #endif 869fafd8bceSBlue Swirl } 870fafd8bceSBlue Swirl break; 8710cc1f4bfSRichard Henderson case ASI_M_MMUREGS: /* write MMU regs */ 8720cc1f4bfSRichard Henderson case ASI_LEON_MMUREGS: /* LEON3 write MMU regs */ 873fafd8bceSBlue Swirl { 874fafd8bceSBlue Swirl int reg = (addr >> 8) & 0x1f; 875fafd8bceSBlue Swirl uint32_t oldreg; 876fafd8bceSBlue Swirl 877fafd8bceSBlue Swirl oldreg = env->mmuregs[reg]; 878fafd8bceSBlue Swirl switch (reg) { 879fafd8bceSBlue Swirl case 0: /* Control Register */ 880fafd8bceSBlue Swirl env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) | 881fafd8bceSBlue Swirl (val & 0x00ffffff); 882af7a06baSRichard Henderson /* Mappings generated during no-fault mode 883af7a06baSRichard Henderson are invalid in normal mode. */ 884af7a06baSRichard Henderson if ((oldreg ^ env->mmuregs[reg]) 885af7a06baSRichard Henderson & (MMU_NF | env->def->mmu_bm)) { 886d10eb08fSAlex Bennée tlb_flush(CPU(cpu)); 887fafd8bceSBlue Swirl } 888fafd8bceSBlue Swirl break; 889fafd8bceSBlue Swirl case 1: /* Context Table Pointer Register */ 890fafd8bceSBlue Swirl env->mmuregs[reg] = val & env->def->mmu_ctpr_mask; 891fafd8bceSBlue Swirl break; 892fafd8bceSBlue Swirl case 2: /* Context Register */ 893fafd8bceSBlue Swirl env->mmuregs[reg] = val & env->def->mmu_cxr_mask; 894fafd8bceSBlue Swirl if (oldreg != env->mmuregs[reg]) { 895fafd8bceSBlue Swirl /* we flush when the MMU context changes because 896fafd8bceSBlue Swirl QEMU has no MMU context support */ 897d10eb08fSAlex Bennée tlb_flush(CPU(cpu)); 898fafd8bceSBlue Swirl } 899fafd8bceSBlue Swirl break; 900fafd8bceSBlue Swirl case 3: /* Synchronous Fault Status Register with Clear */ 901fafd8bceSBlue Swirl case 4: /* Synchronous Fault Address Register */ 902fafd8bceSBlue Swirl break; 903fafd8bceSBlue Swirl case 0x10: /* TLB Replacement Control Register */ 904fafd8bceSBlue Swirl env->mmuregs[reg] = val & env->def->mmu_trcr_mask; 905fafd8bceSBlue Swirl break; 906fafd8bceSBlue Swirl case 0x13: /* Synchronous Fault Status Register with Read 907fafd8bceSBlue Swirl and Clear */ 908fafd8bceSBlue Swirl env->mmuregs[3] = val & env->def->mmu_sfsr_mask; 909fafd8bceSBlue Swirl break; 910fafd8bceSBlue Swirl case 0x14: /* Synchronous Fault Address Register */ 911fafd8bceSBlue Swirl env->mmuregs[4] = val; 912fafd8bceSBlue Swirl break; 913fafd8bceSBlue Swirl default: 914fafd8bceSBlue Swirl env->mmuregs[reg] = val; 915fafd8bceSBlue Swirl break; 916fafd8bceSBlue Swirl } 917fafd8bceSBlue Swirl if (oldreg != env->mmuregs[reg]) { 918fafd8bceSBlue Swirl DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", 919fafd8bceSBlue Swirl reg, oldreg, env->mmuregs[reg]); 920fafd8bceSBlue Swirl } 921fafd8bceSBlue Swirl #ifdef DEBUG_MMU 922fafd8bceSBlue Swirl dump_mmu(stdout, fprintf, env); 923fafd8bceSBlue Swirl #endif 924fafd8bceSBlue Swirl } 925fafd8bceSBlue Swirl break; 9260cc1f4bfSRichard Henderson case ASI_M_TLBDIAG: /* Turbosparc ITLB Diagnostic */ 9270cc1f4bfSRichard Henderson case ASI_M_DIAGS: /* Turbosparc DTLB Diagnostic */ 9280cc1f4bfSRichard Henderson case ASI_M_IODIAG: /* Turbosparc IOTLB Diagnostic */ 929fafd8bceSBlue Swirl break; 9300cc1f4bfSRichard Henderson case ASI_M_TXTC_TAG: /* I-cache tag */ 9310cc1f4bfSRichard Henderson case ASI_M_TXTC_DATA: /* I-cache data */ 9320cc1f4bfSRichard Henderson case ASI_M_DATAC_TAG: /* D-cache tag */ 9330cc1f4bfSRichard Henderson case ASI_M_DATAC_DATA: /* D-cache data */ 9340cc1f4bfSRichard Henderson case ASI_M_FLUSH_PAGE: /* I/D-cache flush page */ 9350cc1f4bfSRichard Henderson case ASI_M_FLUSH_SEG: /* I/D-cache flush segment */ 9360cc1f4bfSRichard Henderson case ASI_M_FLUSH_REGION: /* I/D-cache flush region */ 9370cc1f4bfSRichard Henderson case ASI_M_FLUSH_CTX: /* I/D-cache flush context */ 9380cc1f4bfSRichard Henderson case ASI_M_FLUSH_USER: /* I/D-cache flush user */ 939fafd8bceSBlue Swirl break; 940fafd8bceSBlue Swirl case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ 941fafd8bceSBlue Swirl { 942fafd8bceSBlue Swirl switch (size) { 943fafd8bceSBlue Swirl case 1: 944db3be60dSEdgar E. Iglesias stb_phys(cs->as, (hwaddr)addr 945a8170e5eSAvi Kivity | ((hwaddr)(asi & 0xf) << 32), val); 946fafd8bceSBlue Swirl break; 947fafd8bceSBlue Swirl case 2: 9485ce5944dSEdgar E. Iglesias stw_phys(cs->as, (hwaddr)addr 949a8170e5eSAvi Kivity | ((hwaddr)(asi & 0xf) << 32), val); 950fafd8bceSBlue Swirl break; 951fafd8bceSBlue Swirl case 4: 952fafd8bceSBlue Swirl default: 953ab1da857SEdgar E. Iglesias stl_phys(cs->as, (hwaddr)addr 954a8170e5eSAvi Kivity | ((hwaddr)(asi & 0xf) << 32), val); 955fafd8bceSBlue Swirl break; 956fafd8bceSBlue Swirl case 8: 957f606604fSEdgar E. Iglesias stq_phys(cs->as, (hwaddr)addr 958a8170e5eSAvi Kivity | ((hwaddr)(asi & 0xf) << 32), val); 959fafd8bceSBlue Swirl break; 960fafd8bceSBlue Swirl } 961fafd8bceSBlue Swirl } 962fafd8bceSBlue Swirl break; 963fafd8bceSBlue Swirl case 0x30: /* store buffer tags or Turbosparc secondary cache diagnostic */ 964fafd8bceSBlue Swirl case 0x31: /* store buffer data, Ross RT620 I-cache flush or 965fafd8bceSBlue Swirl Turbosparc snoop RAM */ 966fafd8bceSBlue Swirl case 0x32: /* store buffer control or Turbosparc page table 967fafd8bceSBlue Swirl descriptor diagnostic */ 968fafd8bceSBlue Swirl case 0x36: /* I-cache flash clear */ 969fafd8bceSBlue Swirl case 0x37: /* D-cache flash clear */ 970fafd8bceSBlue Swirl break; 971fafd8bceSBlue Swirl case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/ 972fafd8bceSBlue Swirl { 973fafd8bceSBlue Swirl int reg = (addr >> 8) & 3; 974fafd8bceSBlue Swirl 975fafd8bceSBlue Swirl switch (reg) { 976fafd8bceSBlue Swirl case 0: /* Breakpoint Value (Addr) */ 977fafd8bceSBlue Swirl env->mmubpregs[reg] = (val & 0xfffffffffULL); 978fafd8bceSBlue Swirl break; 979fafd8bceSBlue Swirl case 1: /* Breakpoint Mask */ 980fafd8bceSBlue Swirl env->mmubpregs[reg] = (val & 0xfffffffffULL); 981fafd8bceSBlue Swirl break; 982fafd8bceSBlue Swirl case 2: /* Breakpoint Control */ 983fafd8bceSBlue Swirl env->mmubpregs[reg] = (val & 0x7fULL); 984fafd8bceSBlue Swirl break; 985fafd8bceSBlue Swirl case 3: /* Breakpoint Status */ 986fafd8bceSBlue Swirl env->mmubpregs[reg] = (val & 0xfULL); 987fafd8bceSBlue Swirl break; 988fafd8bceSBlue Swirl } 989fafd8bceSBlue Swirl DPRINTF_MMU("write breakpoint reg[%d] 0x%016x\n", reg, 990fafd8bceSBlue Swirl env->mmuregs[reg]); 991fafd8bceSBlue Swirl } 992fafd8bceSBlue Swirl break; 993fafd8bceSBlue Swirl case 0x49: /* SuperSPARC MMU Counter Breakpoint Value */ 994fafd8bceSBlue Swirl env->mmubpctrv = val & 0xffffffff; 995fafd8bceSBlue Swirl break; 996fafd8bceSBlue Swirl case 0x4a: /* SuperSPARC MMU Counter Breakpoint Control */ 997fafd8bceSBlue Swirl env->mmubpctrc = val & 0x3; 998fafd8bceSBlue Swirl break; 999fafd8bceSBlue Swirl case 0x4b: /* SuperSPARC MMU Counter Breakpoint Status */ 1000fafd8bceSBlue Swirl env->mmubpctrs = val & 0x3; 1001fafd8bceSBlue Swirl break; 1002fafd8bceSBlue Swirl case 0x4c: /* SuperSPARC MMU Breakpoint Action */ 1003fafd8bceSBlue Swirl env->mmubpaction = val & 0x1fff; 1004fafd8bceSBlue Swirl break; 10050cc1f4bfSRichard Henderson case ASI_USERTXT: /* User code access, XXX */ 10060cc1f4bfSRichard Henderson case ASI_KERNELTXT: /* Supervisor code access, XXX */ 1007fafd8bceSBlue Swirl default: 1008c658b94fSAndreas Färber cpu_unassigned_access(CPU(sparc_env_get_cpu(env)), 1009c658b94fSAndreas Färber addr, true, false, asi, size); 1010fafd8bceSBlue Swirl break; 1011918d9a2cSRichard Henderson 1012918d9a2cSRichard Henderson case ASI_USERDATA: /* User data access */ 1013918d9a2cSRichard Henderson case ASI_KERNELDATA: /* Supervisor data access */ 1014918d9a2cSRichard Henderson case ASI_P: 1015918d9a2cSRichard Henderson case ASI_M_BYPASS: /* MMU passthrough */ 1016918d9a2cSRichard Henderson case ASI_LEON_BYPASS: /* LEON MMU passthrough */ 1017918d9a2cSRichard Henderson case ASI_M_BCOPY: /* Block copy, sta access */ 1018918d9a2cSRichard Henderson case ASI_M_BFILL: /* Block fill, stda access */ 1019918d9a2cSRichard Henderson /* These are always handled inline. */ 1020918d9a2cSRichard Henderson g_assert_not_reached(); 1021fafd8bceSBlue Swirl } 1022fafd8bceSBlue Swirl #ifdef DEBUG_ASI 1023fafd8bceSBlue Swirl dump_asi("write", addr, asi, size, val); 1024fafd8bceSBlue Swirl #endif 1025fafd8bceSBlue Swirl } 1026fafd8bceSBlue Swirl 1027fafd8bceSBlue Swirl #endif /* CONFIG_USER_ONLY */ 1028fafd8bceSBlue Swirl #else /* TARGET_SPARC64 */ 1029fafd8bceSBlue Swirl 1030fafd8bceSBlue Swirl #ifdef CONFIG_USER_ONLY 10316850811eSRichard Henderson uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, 10326850811eSRichard Henderson int asi, uint32_t memop) 1033fafd8bceSBlue Swirl { 10346850811eSRichard Henderson int size = 1 << (memop & MO_SIZE); 10356850811eSRichard Henderson int sign = memop & MO_SIGN; 1036fafd8bceSBlue Swirl uint64_t ret = 0; 1037fafd8bceSBlue Swirl 1038fafd8bceSBlue Swirl if (asi < 0x80) { 10392f9d35fcSRichard Henderson cpu_raise_exception_ra(env, TT_PRIV_ACT, GETPC()); 1040fafd8bceSBlue Swirl } 10412f9d35fcSRichard Henderson do_check_align(env, addr, size - 1, GETPC()); 1042fafd8bceSBlue Swirl addr = asi_address_mask(env, asi, addr); 1043fafd8bceSBlue Swirl 1044fafd8bceSBlue Swirl switch (asi) { 10450cc1f4bfSRichard Henderson case ASI_PNF: /* Primary no-fault */ 10460cc1f4bfSRichard Henderson case ASI_PNFL: /* Primary no-fault LE */ 1047918d9a2cSRichard Henderson case ASI_SNF: /* Secondary no-fault */ 1048918d9a2cSRichard Henderson case ASI_SNFL: /* Secondary no-fault LE */ 1049fafd8bceSBlue Swirl if (page_check_range(addr, size, PAGE_READ) == -1) { 1050918d9a2cSRichard Henderson ret = 0; 1051918d9a2cSRichard Henderson break; 1052fafd8bceSBlue Swirl } 1053fafd8bceSBlue Swirl switch (size) { 1054fafd8bceSBlue Swirl case 1: 1055eb513f82SPeter Maydell ret = cpu_ldub_data(env, addr); 1056fafd8bceSBlue Swirl break; 1057fafd8bceSBlue Swirl case 2: 1058eb513f82SPeter Maydell ret = cpu_lduw_data(env, addr); 1059fafd8bceSBlue Swirl break; 1060fafd8bceSBlue Swirl case 4: 1061eb513f82SPeter Maydell ret = cpu_ldl_data(env, addr); 1062fafd8bceSBlue Swirl break; 1063fafd8bceSBlue Swirl case 8: 1064eb513f82SPeter Maydell ret = cpu_ldq_data(env, addr); 1065fafd8bceSBlue Swirl break; 1066918d9a2cSRichard Henderson default: 1067918d9a2cSRichard Henderson g_assert_not_reached(); 1068fafd8bceSBlue Swirl } 1069fafd8bceSBlue Swirl break; 1070918d9a2cSRichard Henderson break; 1071918d9a2cSRichard Henderson 1072918d9a2cSRichard Henderson case ASI_P: /* Primary */ 1073918d9a2cSRichard Henderson case ASI_PL: /* Primary LE */ 10740cc1f4bfSRichard Henderson case ASI_S: /* Secondary */ 10750cc1f4bfSRichard Henderson case ASI_SL: /* Secondary LE */ 1076918d9a2cSRichard Henderson /* These are always handled inline. */ 1077918d9a2cSRichard Henderson g_assert_not_reached(); 1078918d9a2cSRichard Henderson 1079fafd8bceSBlue Swirl default: 1080918d9a2cSRichard Henderson cpu_raise_exception_ra(env, TT_DATA_ACCESS, GETPC()); 1081fafd8bceSBlue Swirl } 1082fafd8bceSBlue Swirl 1083fafd8bceSBlue Swirl /* Convert from little endian */ 1084fafd8bceSBlue Swirl switch (asi) { 10850cc1f4bfSRichard Henderson case ASI_PNFL: /* Primary no-fault LE */ 10860cc1f4bfSRichard Henderson case ASI_SNFL: /* Secondary no-fault LE */ 1087fafd8bceSBlue Swirl switch (size) { 1088fafd8bceSBlue Swirl case 2: 1089fafd8bceSBlue Swirl ret = bswap16(ret); 1090fafd8bceSBlue Swirl break; 1091fafd8bceSBlue Swirl case 4: 1092fafd8bceSBlue Swirl ret = bswap32(ret); 1093fafd8bceSBlue Swirl break; 1094fafd8bceSBlue Swirl case 8: 1095fafd8bceSBlue Swirl ret = bswap64(ret); 1096fafd8bceSBlue Swirl break; 1097fafd8bceSBlue Swirl } 1098fafd8bceSBlue Swirl } 1099fafd8bceSBlue Swirl 1100fafd8bceSBlue Swirl /* Convert to signed number */ 1101fafd8bceSBlue Swirl if (sign) { 1102fafd8bceSBlue Swirl switch (size) { 1103fafd8bceSBlue Swirl case 1: 1104fafd8bceSBlue Swirl ret = (int8_t) ret; 1105fafd8bceSBlue Swirl break; 1106fafd8bceSBlue Swirl case 2: 1107fafd8bceSBlue Swirl ret = (int16_t) ret; 1108fafd8bceSBlue Swirl break; 1109fafd8bceSBlue Swirl case 4: 1110fafd8bceSBlue Swirl ret = (int32_t) ret; 1111fafd8bceSBlue Swirl break; 1112fafd8bceSBlue Swirl } 1113fafd8bceSBlue Swirl } 1114fafd8bceSBlue Swirl #ifdef DEBUG_ASI 1115918d9a2cSRichard Henderson dump_asi("read", addr, asi, size, ret); 1116fafd8bceSBlue Swirl #endif 1117fafd8bceSBlue Swirl return ret; 1118fafd8bceSBlue Swirl } 1119fafd8bceSBlue Swirl 1120fe8d8f0fSBlue Swirl void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val, 11216850811eSRichard Henderson int asi, uint32_t memop) 1122fafd8bceSBlue Swirl { 11236850811eSRichard Henderson int size = 1 << (memop & MO_SIZE); 1124fafd8bceSBlue Swirl #ifdef DEBUG_ASI 1125fafd8bceSBlue Swirl dump_asi("write", addr, asi, size, val); 1126fafd8bceSBlue Swirl #endif 1127fafd8bceSBlue Swirl if (asi < 0x80) { 11282f9d35fcSRichard Henderson cpu_raise_exception_ra(env, TT_PRIV_ACT, GETPC()); 1129fafd8bceSBlue Swirl } 11302f9d35fcSRichard Henderson do_check_align(env, addr, size - 1, GETPC()); 1131fafd8bceSBlue Swirl 1132fafd8bceSBlue Swirl switch (asi) { 11330cc1f4bfSRichard Henderson case ASI_P: /* Primary */ 11340cc1f4bfSRichard Henderson case ASI_PL: /* Primary LE */ 11350cc1f4bfSRichard Henderson case ASI_S: /* Secondary */ 11360cc1f4bfSRichard Henderson case ASI_SL: /* Secondary LE */ 1137918d9a2cSRichard Henderson /* These are always handled inline. */ 1138918d9a2cSRichard Henderson g_assert_not_reached(); 1139fafd8bceSBlue Swirl 11400cc1f4bfSRichard Henderson case ASI_PNF: /* Primary no-fault, RO */ 11410cc1f4bfSRichard Henderson case ASI_SNF: /* Secondary no-fault, RO */ 11420cc1f4bfSRichard Henderson case ASI_PNFL: /* Primary no-fault LE, RO */ 11430cc1f4bfSRichard Henderson case ASI_SNFL: /* Secondary no-fault LE, RO */ 1144fafd8bceSBlue Swirl default: 11452f9d35fcSRichard Henderson cpu_raise_exception_ra(env, TT_DATA_ACCESS, GETPC()); 1146fafd8bceSBlue Swirl } 1147fafd8bceSBlue Swirl } 1148fafd8bceSBlue Swirl 1149fafd8bceSBlue Swirl #else /* CONFIG_USER_ONLY */ 1150fafd8bceSBlue Swirl 11516850811eSRichard Henderson uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, 11526850811eSRichard Henderson int asi, uint32_t memop) 1153fafd8bceSBlue Swirl { 11546850811eSRichard Henderson int size = 1 << (memop & MO_SIZE); 11556850811eSRichard Henderson int sign = memop & MO_SIGN; 11562fad1112SAndreas Färber CPUState *cs = CPU(sparc_env_get_cpu(env)); 1157fafd8bceSBlue Swirl uint64_t ret = 0; 1158fafd8bceSBlue Swirl #if defined(DEBUG_ASI) 1159fafd8bceSBlue Swirl target_ulong last_addr = addr; 1160fafd8bceSBlue Swirl #endif 1161fafd8bceSBlue Swirl 1162fafd8bceSBlue Swirl asi &= 0xff; 1163fafd8bceSBlue Swirl 11647cd39ef2SArtyom Tarasenko do_check_asi(env, asi, GETPC()); 11652f9d35fcSRichard Henderson do_check_align(env, addr, size - 1, GETPC()); 1166fafd8bceSBlue Swirl addr = asi_address_mask(env, asi, addr); 1167fafd8bceSBlue Swirl 1168918d9a2cSRichard Henderson switch (asi) { 1169918d9a2cSRichard Henderson case ASI_PNF: 1170918d9a2cSRichard Henderson case ASI_PNFL: 1171918d9a2cSRichard Henderson case ASI_SNF: 1172918d9a2cSRichard Henderson case ASI_SNFL: 1173918d9a2cSRichard Henderson { 1174918d9a2cSRichard Henderson TCGMemOpIdx oi; 1175918d9a2cSRichard Henderson int idx = (env->pstate & PS_PRIV 1176918d9a2cSRichard Henderson ? (asi & 1 ? MMU_KERNEL_SECONDARY_IDX : MMU_KERNEL_IDX) 1177918d9a2cSRichard Henderson : (asi & 1 ? MMU_USER_SECONDARY_IDX : MMU_USER_IDX)); 1178fafd8bceSBlue Swirl 1179918d9a2cSRichard Henderson if (cpu_get_phys_page_nofault(env, addr, idx) == -1ULL) { 1180fafd8bceSBlue Swirl #ifdef DEBUG_ASI 1181fafd8bceSBlue Swirl dump_asi("read ", last_addr, asi, size, ret); 1182fafd8bceSBlue Swirl #endif 1183918d9a2cSRichard Henderson /* exception_index is set in get_physical_address_data. */ 11842f9d35fcSRichard Henderson cpu_raise_exception_ra(env, cs->exception_index, GETPC()); 1185fafd8bceSBlue Swirl } 1186918d9a2cSRichard Henderson oi = make_memop_idx(memop, idx); 1187918d9a2cSRichard Henderson switch (size) { 1188918d9a2cSRichard Henderson case 1: 1189918d9a2cSRichard Henderson ret = helper_ret_ldub_mmu(env, addr, oi, GETPC()); 1190918d9a2cSRichard Henderson break; 1191918d9a2cSRichard Henderson case 2: 1192918d9a2cSRichard Henderson if (asi & 8) { 1193918d9a2cSRichard Henderson ret = helper_le_lduw_mmu(env, addr, oi, GETPC()); 1194918d9a2cSRichard Henderson } else { 1195918d9a2cSRichard Henderson ret = helper_be_lduw_mmu(env, addr, oi, GETPC()); 1196fafd8bceSBlue Swirl } 1197918d9a2cSRichard Henderson break; 1198918d9a2cSRichard Henderson case 4: 1199918d9a2cSRichard Henderson if (asi & 8) { 1200918d9a2cSRichard Henderson ret = helper_le_ldul_mmu(env, addr, oi, GETPC()); 1201918d9a2cSRichard Henderson } else { 1202918d9a2cSRichard Henderson ret = helper_be_ldul_mmu(env, addr, oi, GETPC()); 1203918d9a2cSRichard Henderson } 1204918d9a2cSRichard Henderson break; 1205918d9a2cSRichard Henderson case 8: 1206918d9a2cSRichard Henderson if (asi & 8) { 1207918d9a2cSRichard Henderson ret = helper_le_ldq_mmu(env, addr, oi, GETPC()); 1208918d9a2cSRichard Henderson } else { 1209918d9a2cSRichard Henderson ret = helper_be_ldq_mmu(env, addr, oi, GETPC()); 1210918d9a2cSRichard Henderson } 1211918d9a2cSRichard Henderson break; 1212918d9a2cSRichard Henderson default: 1213918d9a2cSRichard Henderson g_assert_not_reached(); 1214918d9a2cSRichard Henderson } 1215918d9a2cSRichard Henderson } 1216918d9a2cSRichard Henderson break; 1217fafd8bceSBlue Swirl 12180cc1f4bfSRichard Henderson case ASI_AIUP: /* As if user primary */ 12190cc1f4bfSRichard Henderson case ASI_AIUS: /* As if user secondary */ 12200cc1f4bfSRichard Henderson case ASI_AIUPL: /* As if user primary LE */ 12210cc1f4bfSRichard Henderson case ASI_AIUSL: /* As if user secondary LE */ 12220cc1f4bfSRichard Henderson case ASI_P: /* Primary */ 12230cc1f4bfSRichard Henderson case ASI_S: /* Secondary */ 12240cc1f4bfSRichard Henderson case ASI_PL: /* Primary LE */ 12250cc1f4bfSRichard Henderson case ASI_SL: /* Secondary LE */ 12260cc1f4bfSRichard Henderson case ASI_REAL: /* Bypass */ 12270cc1f4bfSRichard Henderson case ASI_REAL_IO: /* Bypass, non-cacheable */ 12280cc1f4bfSRichard Henderson case ASI_REAL_L: /* Bypass LE */ 12290cc1f4bfSRichard Henderson case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */ 12300cc1f4bfSRichard Henderson case ASI_N: /* Nucleus */ 12310cc1f4bfSRichard Henderson case ASI_NL: /* Nucleus Little Endian (LE) */ 1232918d9a2cSRichard Henderson case ASI_NUCLEUS_QUAD_LDD: /* Nucleus quad LDD 128 bit atomic */ 1233918d9a2cSRichard Henderson case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */ 1234918d9a2cSRichard Henderson case ASI_TWINX_AIUP: /* As if user primary, twinx */ 1235918d9a2cSRichard Henderson case ASI_TWINX_AIUS: /* As if user secondary, twinx */ 1236918d9a2cSRichard Henderson case ASI_TWINX_REAL: /* Real address, twinx */ 1237918d9a2cSRichard Henderson case ASI_TWINX_AIUP_L: /* As if user primary, twinx, LE */ 1238918d9a2cSRichard Henderson case ASI_TWINX_AIUS_L: /* As if user secondary, twinx, LE */ 1239918d9a2cSRichard Henderson case ASI_TWINX_REAL_L: /* Real address, twinx, LE */ 1240918d9a2cSRichard Henderson case ASI_TWINX_N: /* Nucleus, twinx */ 1241918d9a2cSRichard Henderson case ASI_TWINX_NL: /* Nucleus, twinx, LE */ 1242918d9a2cSRichard Henderson /* ??? From the UA2011 document; overlaps BLK_INIT_QUAD_LDD_* */ 1243918d9a2cSRichard Henderson case ASI_TWINX_P: /* Primary, twinx */ 1244918d9a2cSRichard Henderson case ASI_TWINX_PL: /* Primary, twinx, LE */ 1245918d9a2cSRichard Henderson case ASI_TWINX_S: /* Secondary, twinx */ 1246918d9a2cSRichard Henderson case ASI_TWINX_SL: /* Secondary, twinx, LE */ 1247918d9a2cSRichard Henderson /* These are always handled inline. */ 1248918d9a2cSRichard Henderson g_assert_not_reached(); 1249918d9a2cSRichard Henderson 12500cc1f4bfSRichard Henderson case ASI_UPA_CONFIG: /* UPA config */ 1251fafd8bceSBlue Swirl /* XXX */ 1252fafd8bceSBlue Swirl break; 12530cc1f4bfSRichard Henderson case ASI_LSU_CONTROL: /* LSU */ 1254fafd8bceSBlue Swirl ret = env->lsu; 1255fafd8bceSBlue Swirl break; 12560cc1f4bfSRichard Henderson case ASI_IMMU: /* I-MMU regs */ 1257fafd8bceSBlue Swirl { 1258fafd8bceSBlue Swirl int reg = (addr >> 3) & 0xf; 125920395e63SArtyom Tarasenko switch (reg) { 126020395e63SArtyom Tarasenko case 0: 126120395e63SArtyom Tarasenko /* 0x00 I-TSB Tag Target register */ 1262fafd8bceSBlue Swirl ret = ultrasparc_tag_target(env->immu.tag_access); 126320395e63SArtyom Tarasenko break; 126420395e63SArtyom Tarasenko case 3: /* SFSR */ 126520395e63SArtyom Tarasenko ret = env->immu.sfsr; 126620395e63SArtyom Tarasenko break; 126720395e63SArtyom Tarasenko case 5: /* TSB access */ 126820395e63SArtyom Tarasenko ret = env->immu.tsb; 126920395e63SArtyom Tarasenko break; 127020395e63SArtyom Tarasenko case 6: 127120395e63SArtyom Tarasenko /* 0x30 I-TSB Tag Access register */ 127220395e63SArtyom Tarasenko ret = env->immu.tag_access; 127320395e63SArtyom Tarasenko break; 127420395e63SArtyom Tarasenko default: 127520395e63SArtyom Tarasenko cpu_unassigned_access(cs, addr, false, false, 1, size); 127620395e63SArtyom Tarasenko ret = 0; 1277fafd8bceSBlue Swirl } 1278fafd8bceSBlue Swirl break; 1279fafd8bceSBlue Swirl } 12800cc1f4bfSRichard Henderson case ASI_IMMU_TSB_8KB_PTR: /* I-MMU 8k TSB pointer */ 1281fafd8bceSBlue Swirl { 1282fafd8bceSBlue Swirl /* env->immuregs[5] holds I-MMU TSB register value 1283fafd8bceSBlue Swirl env->immuregs[6] holds I-MMU Tag Access register value */ 1284e5673ee4SArtyom Tarasenko ret = ultrasparc_tsb_pointer(env, &env->immu, 0); 1285fafd8bceSBlue Swirl break; 1286fafd8bceSBlue Swirl } 12870cc1f4bfSRichard Henderson case ASI_IMMU_TSB_64KB_PTR: /* I-MMU 64k TSB pointer */ 1288fafd8bceSBlue Swirl { 1289fafd8bceSBlue Swirl /* env->immuregs[5] holds I-MMU TSB register value 1290fafd8bceSBlue Swirl env->immuregs[6] holds I-MMU Tag Access register value */ 1291e5673ee4SArtyom Tarasenko ret = ultrasparc_tsb_pointer(env, &env->immu, 1); 1292fafd8bceSBlue Swirl break; 1293fafd8bceSBlue Swirl } 12940cc1f4bfSRichard Henderson case ASI_ITLB_DATA_ACCESS: /* I-MMU data access */ 1295fafd8bceSBlue Swirl { 1296fafd8bceSBlue Swirl int reg = (addr >> 3) & 0x3f; 1297fafd8bceSBlue Swirl 1298fafd8bceSBlue Swirl ret = env->itlb[reg].tte; 1299fafd8bceSBlue Swirl break; 1300fafd8bceSBlue Swirl } 13010cc1f4bfSRichard Henderson case ASI_ITLB_TAG_READ: /* I-MMU tag read */ 1302fafd8bceSBlue Swirl { 1303fafd8bceSBlue Swirl int reg = (addr >> 3) & 0x3f; 1304fafd8bceSBlue Swirl 1305fafd8bceSBlue Swirl ret = env->itlb[reg].tag; 1306fafd8bceSBlue Swirl break; 1307fafd8bceSBlue Swirl } 13080cc1f4bfSRichard Henderson case ASI_DMMU: /* D-MMU regs */ 1309fafd8bceSBlue Swirl { 1310fafd8bceSBlue Swirl int reg = (addr >> 3) & 0xf; 131120395e63SArtyom Tarasenko switch (reg) { 131220395e63SArtyom Tarasenko case 0: 131320395e63SArtyom Tarasenko /* 0x00 D-TSB Tag Target register */ 1314fafd8bceSBlue Swirl ret = ultrasparc_tag_target(env->dmmu.tag_access); 131520395e63SArtyom Tarasenko break; 131620395e63SArtyom Tarasenko case 1: /* 0x08 Primary Context */ 131720395e63SArtyom Tarasenko ret = env->dmmu.mmu_primary_context; 131820395e63SArtyom Tarasenko break; 131920395e63SArtyom Tarasenko case 2: /* 0x10 Secondary Context */ 132020395e63SArtyom Tarasenko ret = env->dmmu.mmu_secondary_context; 132120395e63SArtyom Tarasenko break; 132220395e63SArtyom Tarasenko case 3: /* SFSR */ 132320395e63SArtyom Tarasenko ret = env->dmmu.sfsr; 132420395e63SArtyom Tarasenko break; 132520395e63SArtyom Tarasenko case 4: /* 0x20 SFAR */ 132620395e63SArtyom Tarasenko ret = env->dmmu.sfar; 132720395e63SArtyom Tarasenko break; 132820395e63SArtyom Tarasenko case 5: /* 0x28 TSB access */ 132920395e63SArtyom Tarasenko ret = env->dmmu.tsb; 133020395e63SArtyom Tarasenko break; 133120395e63SArtyom Tarasenko case 6: /* 0x30 D-TSB Tag Access register */ 133220395e63SArtyom Tarasenko ret = env->dmmu.tag_access; 133320395e63SArtyom Tarasenko break; 133420395e63SArtyom Tarasenko case 7: 133520395e63SArtyom Tarasenko ret = env->dmmu.virtual_watchpoint; 133620395e63SArtyom Tarasenko break; 133720395e63SArtyom Tarasenko case 8: 133820395e63SArtyom Tarasenko ret = env->dmmu.physical_watchpoint; 133920395e63SArtyom Tarasenko break; 134020395e63SArtyom Tarasenko default: 134120395e63SArtyom Tarasenko cpu_unassigned_access(cs, addr, false, false, 1, size); 134220395e63SArtyom Tarasenko ret = 0; 1343fafd8bceSBlue Swirl } 1344fafd8bceSBlue Swirl break; 1345fafd8bceSBlue Swirl } 13460cc1f4bfSRichard Henderson case ASI_DMMU_TSB_8KB_PTR: /* D-MMU 8k TSB pointer */ 1347fafd8bceSBlue Swirl { 1348fafd8bceSBlue Swirl /* env->dmmuregs[5] holds D-MMU TSB register value 1349fafd8bceSBlue Swirl env->dmmuregs[6] holds D-MMU Tag Access register value */ 1350e5673ee4SArtyom Tarasenko ret = ultrasparc_tsb_pointer(env, &env->dmmu, 0); 1351fafd8bceSBlue Swirl break; 1352fafd8bceSBlue Swirl } 13530cc1f4bfSRichard Henderson case ASI_DMMU_TSB_64KB_PTR: /* D-MMU 64k TSB pointer */ 1354fafd8bceSBlue Swirl { 1355fafd8bceSBlue Swirl /* env->dmmuregs[5] holds D-MMU TSB register value 1356fafd8bceSBlue Swirl env->dmmuregs[6] holds D-MMU Tag Access register value */ 1357e5673ee4SArtyom Tarasenko ret = ultrasparc_tsb_pointer(env, &env->dmmu, 1); 1358fafd8bceSBlue Swirl break; 1359fafd8bceSBlue Swirl } 13600cc1f4bfSRichard Henderson case ASI_DTLB_DATA_ACCESS: /* D-MMU data access */ 1361fafd8bceSBlue Swirl { 1362fafd8bceSBlue Swirl int reg = (addr >> 3) & 0x3f; 1363fafd8bceSBlue Swirl 1364fafd8bceSBlue Swirl ret = env->dtlb[reg].tte; 1365fafd8bceSBlue Swirl break; 1366fafd8bceSBlue Swirl } 13670cc1f4bfSRichard Henderson case ASI_DTLB_TAG_READ: /* D-MMU tag read */ 1368fafd8bceSBlue Swirl { 1369fafd8bceSBlue Swirl int reg = (addr >> 3) & 0x3f; 1370fafd8bceSBlue Swirl 1371fafd8bceSBlue Swirl ret = env->dtlb[reg].tag; 1372fafd8bceSBlue Swirl break; 1373fafd8bceSBlue Swirl } 13740cc1f4bfSRichard Henderson case ASI_INTR_DISPATCH_STAT: /* Interrupt dispatch, RO */ 1375361dea40SBlue Swirl break; 13760cc1f4bfSRichard Henderson case ASI_INTR_RECEIVE: /* Interrupt data receive */ 1377361dea40SBlue Swirl ret = env->ivec_status; 1378361dea40SBlue Swirl break; 13790cc1f4bfSRichard Henderson case ASI_INTR_R: /* Incoming interrupt vector, RO */ 1380361dea40SBlue Swirl { 1381361dea40SBlue Swirl int reg = (addr >> 4) & 0x3; 1382361dea40SBlue Swirl if (reg < 3) { 1383361dea40SBlue Swirl ret = env->ivec_data[reg]; 1384361dea40SBlue Swirl } 1385361dea40SBlue Swirl break; 1386361dea40SBlue Swirl } 13874ec3e346SArtyom Tarasenko case ASI_SCRATCHPAD: /* UA2005 privileged scratchpad */ 13884ec3e346SArtyom Tarasenko if (unlikely((addr >= 0x20) && (addr < 0x30))) { 13894ec3e346SArtyom Tarasenko /* Hyperprivileged access only */ 13904ec3e346SArtyom Tarasenko cpu_unassigned_access(cs, addr, false, false, 1, size); 13914ec3e346SArtyom Tarasenko } 13924ec3e346SArtyom Tarasenko /* fall through */ 13934ec3e346SArtyom Tarasenko case ASI_HYP_SCRATCHPAD: /* UA2005 hyperprivileged scratchpad */ 13944ec3e346SArtyom Tarasenko { 13954ec3e346SArtyom Tarasenko unsigned int i = (addr >> 3) & 0x7; 13964ec3e346SArtyom Tarasenko ret = env->scratch[i]; 13974ec3e346SArtyom Tarasenko break; 13984ec3e346SArtyom Tarasenko } 1399*7dd8c076SArtyom Tarasenko case ASI_MMU: /* UA2005 Context ID registers */ 1400*7dd8c076SArtyom Tarasenko switch ((addr >> 3) & 0x3) { 1401*7dd8c076SArtyom Tarasenko case 1: 1402*7dd8c076SArtyom Tarasenko ret = env->dmmu.mmu_primary_context; 1403*7dd8c076SArtyom Tarasenko break; 1404*7dd8c076SArtyom Tarasenko case 2: 1405*7dd8c076SArtyom Tarasenko ret = env->dmmu.mmu_secondary_context; 1406*7dd8c076SArtyom Tarasenko break; 1407*7dd8c076SArtyom Tarasenko default: 1408*7dd8c076SArtyom Tarasenko cpu_unassigned_access(cs, addr, true, false, 1, size); 1409*7dd8c076SArtyom Tarasenko } 1410*7dd8c076SArtyom Tarasenko break; 14110cc1f4bfSRichard Henderson case ASI_DCACHE_DATA: /* D-cache data */ 14120cc1f4bfSRichard Henderson case ASI_DCACHE_TAG: /* D-cache tag access */ 14130cc1f4bfSRichard Henderson case ASI_ESTATE_ERROR_EN: /* E-cache error enable */ 14140cc1f4bfSRichard Henderson case ASI_AFSR: /* E-cache asynchronous fault status */ 14150cc1f4bfSRichard Henderson case ASI_AFAR: /* E-cache asynchronous fault address */ 14160cc1f4bfSRichard Henderson case ASI_EC_TAG_DATA: /* E-cache tag data */ 14170cc1f4bfSRichard Henderson case ASI_IC_INSTR: /* I-cache instruction access */ 14180cc1f4bfSRichard Henderson case ASI_IC_TAG: /* I-cache tag access */ 14190cc1f4bfSRichard Henderson case ASI_IC_PRE_DECODE: /* I-cache predecode */ 14200cc1f4bfSRichard Henderson case ASI_IC_NEXT_FIELD: /* I-cache LRU etc. */ 14210cc1f4bfSRichard Henderson case ASI_EC_W: /* E-cache tag */ 14220cc1f4bfSRichard Henderson case ASI_EC_R: /* E-cache tag */ 1423fafd8bceSBlue Swirl break; 14240cc1f4bfSRichard Henderson case ASI_DMMU_TSB_DIRECT_PTR: /* D-MMU data pointer */ 14250cc1f4bfSRichard Henderson case ASI_ITLB_DATA_IN: /* I-MMU data in, WO */ 14260cc1f4bfSRichard Henderson case ASI_IMMU_DEMAP: /* I-MMU demap, WO */ 14270cc1f4bfSRichard Henderson case ASI_DTLB_DATA_IN: /* D-MMU data in, WO */ 14280cc1f4bfSRichard Henderson case ASI_DMMU_DEMAP: /* D-MMU demap, WO */ 14290cc1f4bfSRichard Henderson case ASI_INTR_W: /* Interrupt vector, WO */ 1430fafd8bceSBlue Swirl default: 14312fad1112SAndreas Färber cpu_unassigned_access(cs, addr, false, false, 1, size); 1432fafd8bceSBlue Swirl ret = 0; 1433fafd8bceSBlue Swirl break; 1434fafd8bceSBlue Swirl } 1435fafd8bceSBlue Swirl 1436fafd8bceSBlue Swirl /* Convert to signed number */ 1437fafd8bceSBlue Swirl if (sign) { 1438fafd8bceSBlue Swirl switch (size) { 1439fafd8bceSBlue Swirl case 1: 1440fafd8bceSBlue Swirl ret = (int8_t) ret; 1441fafd8bceSBlue Swirl break; 1442fafd8bceSBlue Swirl case 2: 1443fafd8bceSBlue Swirl ret = (int16_t) ret; 1444fafd8bceSBlue Swirl break; 1445fafd8bceSBlue Swirl case 4: 1446fafd8bceSBlue Swirl ret = (int32_t) ret; 1447fafd8bceSBlue Swirl break; 1448fafd8bceSBlue Swirl default: 1449fafd8bceSBlue Swirl break; 1450fafd8bceSBlue Swirl } 1451fafd8bceSBlue Swirl } 1452fafd8bceSBlue Swirl #ifdef DEBUG_ASI 1453fafd8bceSBlue Swirl dump_asi("read ", last_addr, asi, size, ret); 1454fafd8bceSBlue Swirl #endif 1455fafd8bceSBlue Swirl return ret; 1456fafd8bceSBlue Swirl } 1457fafd8bceSBlue Swirl 1458fe8d8f0fSBlue Swirl void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val, 14596850811eSRichard Henderson int asi, uint32_t memop) 1460fafd8bceSBlue Swirl { 14616850811eSRichard Henderson int size = 1 << (memop & MO_SIZE); 146200c8cb0aSAndreas Färber SPARCCPU *cpu = sparc_env_get_cpu(env); 146300c8cb0aSAndreas Färber CPUState *cs = CPU(cpu); 146400c8cb0aSAndreas Färber 1465fafd8bceSBlue Swirl #ifdef DEBUG_ASI 1466fafd8bceSBlue Swirl dump_asi("write", addr, asi, size, val); 1467fafd8bceSBlue Swirl #endif 1468fafd8bceSBlue Swirl 1469fafd8bceSBlue Swirl asi &= 0xff; 1470fafd8bceSBlue Swirl 14717cd39ef2SArtyom Tarasenko do_check_asi(env, asi, GETPC()); 14722f9d35fcSRichard Henderson do_check_align(env, addr, size - 1, GETPC()); 1473fafd8bceSBlue Swirl addr = asi_address_mask(env, asi, addr); 1474fafd8bceSBlue Swirl 1475fafd8bceSBlue Swirl switch (asi) { 14760cc1f4bfSRichard Henderson case ASI_AIUP: /* As if user primary */ 14770cc1f4bfSRichard Henderson case ASI_AIUS: /* As if user secondary */ 14780cc1f4bfSRichard Henderson case ASI_AIUPL: /* As if user primary LE */ 14790cc1f4bfSRichard Henderson case ASI_AIUSL: /* As if user secondary LE */ 14800cc1f4bfSRichard Henderson case ASI_P: /* Primary */ 14810cc1f4bfSRichard Henderson case ASI_S: /* Secondary */ 14820cc1f4bfSRichard Henderson case ASI_PL: /* Primary LE */ 14830cc1f4bfSRichard Henderson case ASI_SL: /* Secondary LE */ 14840cc1f4bfSRichard Henderson case ASI_REAL: /* Bypass */ 14850cc1f4bfSRichard Henderson case ASI_REAL_IO: /* Bypass, non-cacheable */ 14860cc1f4bfSRichard Henderson case ASI_REAL_L: /* Bypass LE */ 14870cc1f4bfSRichard Henderson case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */ 14880cc1f4bfSRichard Henderson case ASI_N: /* Nucleus */ 14890cc1f4bfSRichard Henderson case ASI_NL: /* Nucleus Little Endian (LE) */ 1490918d9a2cSRichard Henderson case ASI_NUCLEUS_QUAD_LDD: /* Nucleus quad LDD 128 bit atomic */ 1491918d9a2cSRichard Henderson case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */ 1492918d9a2cSRichard Henderson case ASI_TWINX_AIUP: /* As if user primary, twinx */ 1493918d9a2cSRichard Henderson case ASI_TWINX_AIUS: /* As if user secondary, twinx */ 1494918d9a2cSRichard Henderson case ASI_TWINX_REAL: /* Real address, twinx */ 1495918d9a2cSRichard Henderson case ASI_TWINX_AIUP_L: /* As if user primary, twinx, LE */ 1496918d9a2cSRichard Henderson case ASI_TWINX_AIUS_L: /* As if user secondary, twinx, LE */ 1497918d9a2cSRichard Henderson case ASI_TWINX_REAL_L: /* Real address, twinx, LE */ 1498918d9a2cSRichard Henderson case ASI_TWINX_N: /* Nucleus, twinx */ 1499918d9a2cSRichard Henderson case ASI_TWINX_NL: /* Nucleus, twinx, LE */ 1500918d9a2cSRichard Henderson /* ??? From the UA2011 document; overlaps BLK_INIT_QUAD_LDD_* */ 1501918d9a2cSRichard Henderson case ASI_TWINX_P: /* Primary, twinx */ 1502918d9a2cSRichard Henderson case ASI_TWINX_PL: /* Primary, twinx, LE */ 1503918d9a2cSRichard Henderson case ASI_TWINX_S: /* Secondary, twinx */ 1504918d9a2cSRichard Henderson case ASI_TWINX_SL: /* Secondary, twinx, LE */ 1505918d9a2cSRichard Henderson /* These are always handled inline. */ 1506918d9a2cSRichard Henderson g_assert_not_reached(); 150715f746ceSArtyom Tarasenko /* these ASIs have different functions on UltraSPARC-IIIi 150815f746ceSArtyom Tarasenko * and UA2005 CPUs. Use the explicit numbers to avoid confusion 150915f746ceSArtyom Tarasenko */ 151015f746ceSArtyom Tarasenko case 0x31: 151115f746ceSArtyom Tarasenko case 0x32: 151215f746ceSArtyom Tarasenko case 0x39: 151315f746ceSArtyom Tarasenko case 0x3a: 151415f746ceSArtyom Tarasenko if (cpu_has_hypervisor(env)) { 151515f746ceSArtyom Tarasenko /* UA2005 151615f746ceSArtyom Tarasenko * ASI_DMMU_CTX_ZERO_TSB_BASE_PS0 151715f746ceSArtyom Tarasenko * ASI_DMMU_CTX_ZERO_TSB_BASE_PS1 151815f746ceSArtyom Tarasenko * ASI_DMMU_CTX_NONZERO_TSB_BASE_PS0 151915f746ceSArtyom Tarasenko * ASI_DMMU_CTX_NONZERO_TSB_BASE_PS1 152015f746ceSArtyom Tarasenko */ 152115f746ceSArtyom Tarasenko int idx = ((asi & 2) >> 1) | ((asi & 8) >> 2); 152215f746ceSArtyom Tarasenko env->dmmu.sun4v_tsb_pointers[idx] = val; 152315f746ceSArtyom Tarasenko } else { 152415f746ceSArtyom Tarasenko helper_raise_exception(env, TT_ILL_INSN); 152515f746ceSArtyom Tarasenko } 152615f746ceSArtyom Tarasenko break; 152715f746ceSArtyom Tarasenko case 0x33: 152815f746ceSArtyom Tarasenko case 0x3b: 152915f746ceSArtyom Tarasenko if (cpu_has_hypervisor(env)) { 153015f746ceSArtyom Tarasenko /* UA2005 153115f746ceSArtyom Tarasenko * ASI_DMMU_CTX_ZERO_CONFIG 153215f746ceSArtyom Tarasenko * ASI_DMMU_CTX_NONZERO_CONFIG 153315f746ceSArtyom Tarasenko */ 153415f746ceSArtyom Tarasenko env->dmmu.sun4v_ctx_config[(asi & 8) >> 3] = val; 153515f746ceSArtyom Tarasenko } else { 153615f746ceSArtyom Tarasenko helper_raise_exception(env, TT_ILL_INSN); 153715f746ceSArtyom Tarasenko } 153815f746ceSArtyom Tarasenko break; 153915f746ceSArtyom Tarasenko case 0x35: 154015f746ceSArtyom Tarasenko case 0x36: 154115f746ceSArtyom Tarasenko case 0x3d: 154215f746ceSArtyom Tarasenko case 0x3e: 154315f746ceSArtyom Tarasenko if (cpu_has_hypervisor(env)) { 154415f746ceSArtyom Tarasenko /* UA2005 154515f746ceSArtyom Tarasenko * ASI_IMMU_CTX_ZERO_TSB_BASE_PS0 154615f746ceSArtyom Tarasenko * ASI_IMMU_CTX_ZERO_TSB_BASE_PS1 154715f746ceSArtyom Tarasenko * ASI_IMMU_CTX_NONZERO_TSB_BASE_PS0 154815f746ceSArtyom Tarasenko * ASI_IMMU_CTX_NONZERO_TSB_BASE_PS1 154915f746ceSArtyom Tarasenko */ 155015f746ceSArtyom Tarasenko int idx = ((asi & 2) >> 1) | ((asi & 8) >> 2); 155115f746ceSArtyom Tarasenko env->immu.sun4v_tsb_pointers[idx] = val; 155215f746ceSArtyom Tarasenko } else { 155315f746ceSArtyom Tarasenko helper_raise_exception(env, TT_ILL_INSN); 155415f746ceSArtyom Tarasenko } 155515f746ceSArtyom Tarasenko break; 155615f746ceSArtyom Tarasenko case 0x37: 155715f746ceSArtyom Tarasenko case 0x3f: 155815f746ceSArtyom Tarasenko if (cpu_has_hypervisor(env)) { 155915f746ceSArtyom Tarasenko /* UA2005 156015f746ceSArtyom Tarasenko * ASI_IMMU_CTX_ZERO_CONFIG 156115f746ceSArtyom Tarasenko * ASI_IMMU_CTX_NONZERO_CONFIG 156215f746ceSArtyom Tarasenko */ 156315f746ceSArtyom Tarasenko env->immu.sun4v_ctx_config[(asi & 8) >> 3] = val; 156415f746ceSArtyom Tarasenko } else { 156515f746ceSArtyom Tarasenko helper_raise_exception(env, TT_ILL_INSN); 156615f746ceSArtyom Tarasenko } 156715f746ceSArtyom Tarasenko break; 15680cc1f4bfSRichard Henderson case ASI_UPA_CONFIG: /* UPA config */ 1569fafd8bceSBlue Swirl /* XXX */ 1570fafd8bceSBlue Swirl return; 15710cc1f4bfSRichard Henderson case ASI_LSU_CONTROL: /* LSU */ 1572fafd8bceSBlue Swirl env->lsu = val & (DMMU_E | IMMU_E); 1573fafd8bceSBlue Swirl return; 15740cc1f4bfSRichard Henderson case ASI_IMMU: /* I-MMU regs */ 1575fafd8bceSBlue Swirl { 1576fafd8bceSBlue Swirl int reg = (addr >> 3) & 0xf; 1577fafd8bceSBlue Swirl uint64_t oldreg; 1578fafd8bceSBlue Swirl 157996df2bc9SArtyom Tarasenko oldreg = env->immu.mmuregs[reg]; 1580fafd8bceSBlue Swirl switch (reg) { 1581fafd8bceSBlue Swirl case 0: /* RO */ 1582fafd8bceSBlue Swirl return; 1583fafd8bceSBlue Swirl case 1: /* Not in I-MMU */ 1584fafd8bceSBlue Swirl case 2: 1585fafd8bceSBlue Swirl return; 1586fafd8bceSBlue Swirl case 3: /* SFSR */ 1587fafd8bceSBlue Swirl if ((val & 1) == 0) { 1588fafd8bceSBlue Swirl val = 0; /* Clear SFSR */ 1589fafd8bceSBlue Swirl } 1590fafd8bceSBlue Swirl env->immu.sfsr = val; 1591fafd8bceSBlue Swirl break; 1592fafd8bceSBlue Swirl case 4: /* RO */ 1593fafd8bceSBlue Swirl return; 1594fafd8bceSBlue Swirl case 5: /* TSB access */ 1595fafd8bceSBlue Swirl DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016" 1596fafd8bceSBlue Swirl PRIx64 "\n", env->immu.tsb, val); 1597fafd8bceSBlue Swirl env->immu.tsb = val; 1598fafd8bceSBlue Swirl break; 1599fafd8bceSBlue Swirl case 6: /* Tag access */ 1600fafd8bceSBlue Swirl env->immu.tag_access = val; 1601fafd8bceSBlue Swirl break; 1602fafd8bceSBlue Swirl case 7: 1603fafd8bceSBlue Swirl case 8: 1604fafd8bceSBlue Swirl return; 1605fafd8bceSBlue Swirl default: 160620395e63SArtyom Tarasenko cpu_unassigned_access(cs, addr, true, false, 1, size); 1607fafd8bceSBlue Swirl break; 1608fafd8bceSBlue Swirl } 1609fafd8bceSBlue Swirl 161096df2bc9SArtyom Tarasenko if (oldreg != env->immu.mmuregs[reg]) { 1611fafd8bceSBlue Swirl DPRINTF_MMU("immu change reg[%d]: 0x%016" PRIx64 " -> 0x%016" 1612fafd8bceSBlue Swirl PRIx64 "\n", reg, oldreg, env->immuregs[reg]); 1613fafd8bceSBlue Swirl } 1614fafd8bceSBlue Swirl #ifdef DEBUG_MMU 1615fafd8bceSBlue Swirl dump_mmu(stdout, fprintf, env); 1616fafd8bceSBlue Swirl #endif 1617fafd8bceSBlue Swirl return; 1618fafd8bceSBlue Swirl } 16190cc1f4bfSRichard Henderson case ASI_ITLB_DATA_IN: /* I-MMU data in */ 1620fafd8bceSBlue Swirl replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env); 1621fafd8bceSBlue Swirl return; 16220cc1f4bfSRichard Henderson case ASI_ITLB_DATA_ACCESS: /* I-MMU data access */ 1623fafd8bceSBlue Swirl { 1624fafd8bceSBlue Swirl /* TODO: auto demap */ 1625fafd8bceSBlue Swirl 1626fafd8bceSBlue Swirl unsigned int i = (addr >> 3) & 0x3f; 1627fafd8bceSBlue Swirl 1628fafd8bceSBlue Swirl replace_tlb_entry(&env->itlb[i], env->immu.tag_access, val, env); 1629fafd8bceSBlue Swirl 1630fafd8bceSBlue Swirl #ifdef DEBUG_MMU 1631fafd8bceSBlue Swirl DPRINTF_MMU("immu data access replaced entry [%i]\n", i); 1632fafd8bceSBlue Swirl dump_mmu(stdout, fprintf, env); 1633fafd8bceSBlue Swirl #endif 1634fafd8bceSBlue Swirl return; 1635fafd8bceSBlue Swirl } 16360cc1f4bfSRichard Henderson case ASI_IMMU_DEMAP: /* I-MMU demap */ 1637fafd8bceSBlue Swirl demap_tlb(env->itlb, addr, "immu", env); 1638fafd8bceSBlue Swirl return; 16390cc1f4bfSRichard Henderson case ASI_DMMU: /* D-MMU regs */ 1640fafd8bceSBlue Swirl { 1641fafd8bceSBlue Swirl int reg = (addr >> 3) & 0xf; 1642fafd8bceSBlue Swirl uint64_t oldreg; 1643fafd8bceSBlue Swirl 164496df2bc9SArtyom Tarasenko oldreg = env->dmmu.mmuregs[reg]; 1645fafd8bceSBlue Swirl switch (reg) { 1646fafd8bceSBlue Swirl case 0: /* RO */ 1647fafd8bceSBlue Swirl case 4: 1648fafd8bceSBlue Swirl return; 1649fafd8bceSBlue Swirl case 3: /* SFSR */ 1650fafd8bceSBlue Swirl if ((val & 1) == 0) { 1651fafd8bceSBlue Swirl val = 0; /* Clear SFSR, Fault address */ 1652fafd8bceSBlue Swirl env->dmmu.sfar = 0; 1653fafd8bceSBlue Swirl } 1654fafd8bceSBlue Swirl env->dmmu.sfsr = val; 1655fafd8bceSBlue Swirl break; 1656fafd8bceSBlue Swirl case 1: /* Primary context */ 1657fafd8bceSBlue Swirl env->dmmu.mmu_primary_context = val; 1658fafd8bceSBlue Swirl /* can be optimized to only flush MMU_USER_IDX 1659fafd8bceSBlue Swirl and MMU_KERNEL_IDX entries */ 1660d10eb08fSAlex Bennée tlb_flush(CPU(cpu)); 1661fafd8bceSBlue Swirl break; 1662fafd8bceSBlue Swirl case 2: /* Secondary context */ 1663fafd8bceSBlue Swirl env->dmmu.mmu_secondary_context = val; 1664fafd8bceSBlue Swirl /* can be optimized to only flush MMU_USER_SECONDARY_IDX 1665fafd8bceSBlue Swirl and MMU_KERNEL_SECONDARY_IDX entries */ 1666d10eb08fSAlex Bennée tlb_flush(CPU(cpu)); 1667fafd8bceSBlue Swirl break; 1668fafd8bceSBlue Swirl case 5: /* TSB access */ 1669fafd8bceSBlue Swirl DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016" 1670fafd8bceSBlue Swirl PRIx64 "\n", env->dmmu.tsb, val); 1671fafd8bceSBlue Swirl env->dmmu.tsb = val; 1672fafd8bceSBlue Swirl break; 1673fafd8bceSBlue Swirl case 6: /* Tag access */ 1674fafd8bceSBlue Swirl env->dmmu.tag_access = val; 1675fafd8bceSBlue Swirl break; 1676fafd8bceSBlue Swirl case 7: /* Virtual Watchpoint */ 167720395e63SArtyom Tarasenko env->dmmu.virtual_watchpoint = val; 167820395e63SArtyom Tarasenko break; 1679fafd8bceSBlue Swirl case 8: /* Physical Watchpoint */ 168020395e63SArtyom Tarasenko env->dmmu.physical_watchpoint = val; 168120395e63SArtyom Tarasenko break; 1682fafd8bceSBlue Swirl default: 168320395e63SArtyom Tarasenko cpu_unassigned_access(cs, addr, true, false, 1, size); 1684fafd8bceSBlue Swirl break; 1685fafd8bceSBlue Swirl } 1686fafd8bceSBlue Swirl 168796df2bc9SArtyom Tarasenko if (oldreg != env->dmmu.mmuregs[reg]) { 1688fafd8bceSBlue Swirl DPRINTF_MMU("dmmu change reg[%d]: 0x%016" PRIx64 " -> 0x%016" 1689fafd8bceSBlue Swirl PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]); 1690fafd8bceSBlue Swirl } 1691fafd8bceSBlue Swirl #ifdef DEBUG_MMU 1692fafd8bceSBlue Swirl dump_mmu(stdout, fprintf, env); 1693fafd8bceSBlue Swirl #endif 1694fafd8bceSBlue Swirl return; 1695fafd8bceSBlue Swirl } 16960cc1f4bfSRichard Henderson case ASI_DTLB_DATA_IN: /* D-MMU data in */ 1697fafd8bceSBlue Swirl replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env); 1698fafd8bceSBlue Swirl return; 16990cc1f4bfSRichard Henderson case ASI_DTLB_DATA_ACCESS: /* D-MMU data access */ 1700fafd8bceSBlue Swirl { 1701fafd8bceSBlue Swirl unsigned int i = (addr >> 3) & 0x3f; 1702fafd8bceSBlue Swirl 1703fafd8bceSBlue Swirl replace_tlb_entry(&env->dtlb[i], env->dmmu.tag_access, val, env); 1704fafd8bceSBlue Swirl 1705fafd8bceSBlue Swirl #ifdef DEBUG_MMU 1706fafd8bceSBlue Swirl DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i); 1707fafd8bceSBlue Swirl dump_mmu(stdout, fprintf, env); 1708fafd8bceSBlue Swirl #endif 1709fafd8bceSBlue Swirl return; 1710fafd8bceSBlue Swirl } 17110cc1f4bfSRichard Henderson case ASI_DMMU_DEMAP: /* D-MMU demap */ 1712fafd8bceSBlue Swirl demap_tlb(env->dtlb, addr, "dmmu", env); 1713fafd8bceSBlue Swirl return; 17140cc1f4bfSRichard Henderson case ASI_INTR_RECEIVE: /* Interrupt data receive */ 1715361dea40SBlue Swirl env->ivec_status = val & 0x20; 1716fafd8bceSBlue Swirl return; 17174ec3e346SArtyom Tarasenko case ASI_SCRATCHPAD: /* UA2005 privileged scratchpad */ 17184ec3e346SArtyom Tarasenko if (unlikely((addr >= 0x20) && (addr < 0x30))) { 17194ec3e346SArtyom Tarasenko /* Hyperprivileged access only */ 17204ec3e346SArtyom Tarasenko cpu_unassigned_access(cs, addr, true, false, 1, size); 17214ec3e346SArtyom Tarasenko } 17224ec3e346SArtyom Tarasenko /* fall through */ 17234ec3e346SArtyom Tarasenko case ASI_HYP_SCRATCHPAD: /* UA2005 hyperprivileged scratchpad */ 17244ec3e346SArtyom Tarasenko { 17254ec3e346SArtyom Tarasenko unsigned int i = (addr >> 3) & 0x7; 17264ec3e346SArtyom Tarasenko env->scratch[i] = val; 17274ec3e346SArtyom Tarasenko return; 17284ec3e346SArtyom Tarasenko } 1729*7dd8c076SArtyom Tarasenko case ASI_MMU: /* UA2005 Context ID registers */ 1730*7dd8c076SArtyom Tarasenko { 1731*7dd8c076SArtyom Tarasenko switch ((addr >> 3) & 0x3) { 1732*7dd8c076SArtyom Tarasenko case 1: 1733*7dd8c076SArtyom Tarasenko env->dmmu.mmu_primary_context = val; 1734*7dd8c076SArtyom Tarasenko env->immu.mmu_primary_context = val; 1735*7dd8c076SArtyom Tarasenko tlb_flush_by_mmuidx(CPU(cpu), MMU_USER_IDX, MMU_KERNEL_IDX, -1); 1736*7dd8c076SArtyom Tarasenko break; 1737*7dd8c076SArtyom Tarasenko case 2: 1738*7dd8c076SArtyom Tarasenko env->dmmu.mmu_secondary_context = val; 1739*7dd8c076SArtyom Tarasenko env->immu.mmu_secondary_context = val; 1740*7dd8c076SArtyom Tarasenko tlb_flush_by_mmuidx(CPU(cpu), MMU_USER_SECONDARY_IDX, 1741*7dd8c076SArtyom Tarasenko MMU_KERNEL_SECONDARY_IDX, -1); 1742*7dd8c076SArtyom Tarasenko break; 1743*7dd8c076SArtyom Tarasenko default: 1744*7dd8c076SArtyom Tarasenko cpu_unassigned_access(cs, addr, true, false, 1, size); 1745*7dd8c076SArtyom Tarasenko } 1746*7dd8c076SArtyom Tarasenko } 1747*7dd8c076SArtyom Tarasenko return; 17482f1b5292SArtyom Tarasenko case ASI_QUEUE: /* UA2005 CPU mondo queue */ 17490cc1f4bfSRichard Henderson case ASI_DCACHE_DATA: /* D-cache data */ 17500cc1f4bfSRichard Henderson case ASI_DCACHE_TAG: /* D-cache tag access */ 17510cc1f4bfSRichard Henderson case ASI_ESTATE_ERROR_EN: /* E-cache error enable */ 17520cc1f4bfSRichard Henderson case ASI_AFSR: /* E-cache asynchronous fault status */ 17530cc1f4bfSRichard Henderson case ASI_AFAR: /* E-cache asynchronous fault address */ 17540cc1f4bfSRichard Henderson case ASI_EC_TAG_DATA: /* E-cache tag data */ 17550cc1f4bfSRichard Henderson case ASI_IC_INSTR: /* I-cache instruction access */ 17560cc1f4bfSRichard Henderson case ASI_IC_TAG: /* I-cache tag access */ 17570cc1f4bfSRichard Henderson case ASI_IC_PRE_DECODE: /* I-cache predecode */ 17580cc1f4bfSRichard Henderson case ASI_IC_NEXT_FIELD: /* I-cache LRU etc. */ 17590cc1f4bfSRichard Henderson case ASI_EC_W: /* E-cache tag */ 17600cc1f4bfSRichard Henderson case ASI_EC_R: /* E-cache tag */ 1761fafd8bceSBlue Swirl return; 17620cc1f4bfSRichard Henderson case ASI_IMMU_TSB_8KB_PTR: /* I-MMU 8k TSB pointer, RO */ 17630cc1f4bfSRichard Henderson case ASI_IMMU_TSB_64KB_PTR: /* I-MMU 64k TSB pointer, RO */ 17640cc1f4bfSRichard Henderson case ASI_ITLB_TAG_READ: /* I-MMU tag read, RO */ 17650cc1f4bfSRichard Henderson case ASI_DMMU_TSB_8KB_PTR: /* D-MMU 8k TSB pointer, RO */ 17660cc1f4bfSRichard Henderson case ASI_DMMU_TSB_64KB_PTR: /* D-MMU 64k TSB pointer, RO */ 17670cc1f4bfSRichard Henderson case ASI_DMMU_TSB_DIRECT_PTR: /* D-MMU data pointer, RO */ 17680cc1f4bfSRichard Henderson case ASI_DTLB_TAG_READ: /* D-MMU tag read, RO */ 17690cc1f4bfSRichard Henderson case ASI_INTR_DISPATCH_STAT: /* Interrupt dispatch, RO */ 17700cc1f4bfSRichard Henderson case ASI_INTR_R: /* Incoming interrupt vector, RO */ 17710cc1f4bfSRichard Henderson case ASI_PNF: /* Primary no-fault, RO */ 17720cc1f4bfSRichard Henderson case ASI_SNF: /* Secondary no-fault, RO */ 17730cc1f4bfSRichard Henderson case ASI_PNFL: /* Primary no-fault LE, RO */ 17740cc1f4bfSRichard Henderson case ASI_SNFL: /* Secondary no-fault LE, RO */ 1775fafd8bceSBlue Swirl default: 17762fad1112SAndreas Färber cpu_unassigned_access(cs, addr, true, false, 1, size); 1777fafd8bceSBlue Swirl return; 1778fafd8bceSBlue Swirl } 1779fafd8bceSBlue Swirl } 1780fafd8bceSBlue Swirl #endif /* CONFIG_USER_ONLY */ 1781fafd8bceSBlue Swirl #endif /* TARGET_SPARC64 */ 1782fafd8bceSBlue Swirl 1783fafd8bceSBlue Swirl #if !defined(CONFIG_USER_ONLY) 1784fe8d8f0fSBlue Swirl #ifndef TARGET_SPARC64 1785c658b94fSAndreas Färber void sparc_cpu_unassigned_access(CPUState *cs, hwaddr addr, 1786c658b94fSAndreas Färber bool is_write, bool is_exec, int is_asi, 1787c658b94fSAndreas Färber unsigned size) 1788fafd8bceSBlue Swirl { 1789c658b94fSAndreas Färber SPARCCPU *cpu = SPARC_CPU(cs); 1790c658b94fSAndreas Färber CPUSPARCState *env = &cpu->env; 1791fafd8bceSBlue Swirl int fault_type; 1792fafd8bceSBlue Swirl 1793fafd8bceSBlue Swirl #ifdef DEBUG_UNASSIGNED 1794fafd8bceSBlue Swirl if (is_asi) { 1795fafd8bceSBlue Swirl printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx 1796fafd8bceSBlue Swirl " asi 0x%02x from " TARGET_FMT_lx "\n", 1797fafd8bceSBlue Swirl is_exec ? "exec" : is_write ? "write" : "read", size, 1798fafd8bceSBlue Swirl size == 1 ? "" : "s", addr, is_asi, env->pc); 1799fafd8bceSBlue Swirl } else { 1800fafd8bceSBlue Swirl printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx 1801fafd8bceSBlue Swirl " from " TARGET_FMT_lx "\n", 1802fafd8bceSBlue Swirl is_exec ? "exec" : is_write ? "write" : "read", size, 1803fafd8bceSBlue Swirl size == 1 ? "" : "s", addr, env->pc); 1804fafd8bceSBlue Swirl } 1805fafd8bceSBlue Swirl #endif 1806fafd8bceSBlue Swirl /* Don't overwrite translation and access faults */ 1807fafd8bceSBlue Swirl fault_type = (env->mmuregs[3] & 0x1c) >> 2; 1808fafd8bceSBlue Swirl if ((fault_type > 4) || (fault_type == 0)) { 1809fafd8bceSBlue Swirl env->mmuregs[3] = 0; /* Fault status register */ 1810fafd8bceSBlue Swirl if (is_asi) { 1811fafd8bceSBlue Swirl env->mmuregs[3] |= 1 << 16; 1812fafd8bceSBlue Swirl } 1813fafd8bceSBlue Swirl if (env->psrs) { 1814fafd8bceSBlue Swirl env->mmuregs[3] |= 1 << 5; 1815fafd8bceSBlue Swirl } 1816fafd8bceSBlue Swirl if (is_exec) { 1817fafd8bceSBlue Swirl env->mmuregs[3] |= 1 << 6; 1818fafd8bceSBlue Swirl } 1819fafd8bceSBlue Swirl if (is_write) { 1820fafd8bceSBlue Swirl env->mmuregs[3] |= 1 << 7; 1821fafd8bceSBlue Swirl } 1822fafd8bceSBlue Swirl env->mmuregs[3] |= (5 << 2) | 2; 1823fafd8bceSBlue Swirl /* SuperSPARC will never place instruction fault addresses in the FAR */ 1824fafd8bceSBlue Swirl if (!is_exec) { 1825fafd8bceSBlue Swirl env->mmuregs[4] = addr; /* Fault address register */ 1826fafd8bceSBlue Swirl } 1827fafd8bceSBlue Swirl } 1828fafd8bceSBlue Swirl /* overflow (same type fault was not read before another fault) */ 1829fafd8bceSBlue Swirl if (fault_type == ((env->mmuregs[3] & 0x1c)) >> 2) { 1830fafd8bceSBlue Swirl env->mmuregs[3] |= 1; 1831fafd8bceSBlue Swirl } 1832fafd8bceSBlue Swirl 1833fafd8bceSBlue Swirl if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) { 18342f9d35fcSRichard Henderson int tt = is_exec ? TT_CODE_ACCESS : TT_DATA_ACCESS; 18352f9d35fcSRichard Henderson cpu_raise_exception_ra(env, tt, GETPC()); 1836fafd8bceSBlue Swirl } 1837fafd8bceSBlue Swirl 1838fafd8bceSBlue Swirl /* flush neverland mappings created during no-fault mode, 1839fafd8bceSBlue Swirl so the sequential MMU faults report proper fault types */ 1840fafd8bceSBlue Swirl if (env->mmuregs[0] & MMU_NF) { 1841d10eb08fSAlex Bennée tlb_flush(cs); 1842fafd8bceSBlue Swirl } 1843fafd8bceSBlue Swirl } 1844fafd8bceSBlue Swirl #else 1845c658b94fSAndreas Färber void sparc_cpu_unassigned_access(CPUState *cs, hwaddr addr, 1846c658b94fSAndreas Färber bool is_write, bool is_exec, int is_asi, 1847c658b94fSAndreas Färber unsigned size) 1848fafd8bceSBlue Swirl { 1849c658b94fSAndreas Färber SPARCCPU *cpu = SPARC_CPU(cs); 1850c658b94fSAndreas Färber CPUSPARCState *env = &cpu->env; 1851c658b94fSAndreas Färber 1852fafd8bceSBlue Swirl #ifdef DEBUG_UNASSIGNED 1853fafd8bceSBlue Swirl printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx 1854fafd8bceSBlue Swirl "\n", addr, env->pc); 1855fafd8bceSBlue Swirl #endif 1856fafd8bceSBlue Swirl 18571ceca928SArtyom Tarasenko if (is_exec) { /* XXX has_hypervisor */ 18581ceca928SArtyom Tarasenko if (env->lsu & (IMMU_E)) { 18591ceca928SArtyom Tarasenko cpu_raise_exception_ra(env, TT_CODE_ACCESS, GETPC()); 18601ceca928SArtyom Tarasenko } else if (cpu_has_hypervisor(env) && !(env->hpstate & HS_PRIV)) { 18611ceca928SArtyom Tarasenko cpu_raise_exception_ra(env, TT_INSN_REAL_TRANSLATION_MISS, GETPC()); 18621ceca928SArtyom Tarasenko } 18631ceca928SArtyom Tarasenko } else { 18641ceca928SArtyom Tarasenko if (env->lsu & (DMMU_E)) { 18651ceca928SArtyom Tarasenko cpu_raise_exception_ra(env, TT_DATA_ACCESS, GETPC()); 18661ceca928SArtyom Tarasenko } else if (cpu_has_hypervisor(env) && !(env->hpstate & HS_PRIV)) { 18671ceca928SArtyom Tarasenko cpu_raise_exception_ra(env, TT_DATA_REAL_TRANSLATION_MISS, GETPC()); 18681ceca928SArtyom Tarasenko } 18691ceca928SArtyom Tarasenko } 1870fafd8bceSBlue Swirl } 1871fafd8bceSBlue Swirl #endif 1872fafd8bceSBlue Swirl #endif 18730184e266SBlue Swirl 1874c28ae41eSRichard Henderson #if !defined(CONFIG_USER_ONLY) 1875b35399bbSSergey Sorokin void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr, 1876b35399bbSSergey Sorokin MMUAccessType access_type, 1877b35399bbSSergey Sorokin int mmu_idx, 1878b35399bbSSergey Sorokin uintptr_t retaddr) 18790184e266SBlue Swirl { 188093e22326SPaolo Bonzini SPARCCPU *cpu = SPARC_CPU(cs); 188193e22326SPaolo Bonzini CPUSPARCState *env = &cpu->env; 188293e22326SPaolo Bonzini 18830184e266SBlue Swirl #ifdef DEBUG_UNALIGNED 18840184e266SBlue Swirl printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx 18850184e266SBlue Swirl "\n", addr, env->pc); 18860184e266SBlue Swirl #endif 18872f9d35fcSRichard Henderson cpu_raise_exception_ra(env, TT_UNALIGNED, retaddr); 18880184e266SBlue Swirl } 18890184e266SBlue Swirl 18900184e266SBlue Swirl /* try to fill the TLB and return an exception if error. If retaddr is 18910184e266SBlue Swirl NULL, it means that the function was called in C code (i.e. not 18920184e266SBlue Swirl from generated code or from helper.c) */ 18930184e266SBlue Swirl /* XXX: fix it to restore all registers */ 1894b35399bbSSergey Sorokin void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type, 1895b35399bbSSergey Sorokin int mmu_idx, uintptr_t retaddr) 18960184e266SBlue Swirl { 18970184e266SBlue Swirl int ret; 18980184e266SBlue Swirl 1899b35399bbSSergey Sorokin ret = sparc_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx); 19000184e266SBlue Swirl if (ret) { 19012f9d35fcSRichard Henderson cpu_loop_exit_restore(cs, retaddr); 19020184e266SBlue Swirl } 19030184e266SBlue Swirl } 19040184e266SBlue Swirl #endif 1905