mmu.c (3924a9aa02fa00a256ddcfe2d6a08bc410ddcaaf) | mmu.c (f0f7e7f7b284f536389a3c5b67de681055325317) |
---|---|
1/* 2 * Microblaze MMU emulation for qemu. 3 * 4 * Copyright (c) 2009 Edgar E. Iglesias 5 * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public --- 166 unchanged lines hidden (view full) --- 175 } 176done: 177 D(qemu_log("MMU vaddr=%" PRIx64 " rw=%d tlb_wr=%d tlb_ex=%d hit=%d\n", 178 vaddr, rw, tlb_wr, tlb_ex, hit)); 179 return hit; 180} 181 182/* Writes/reads to the MMU's special regs end up here. */ | 1/* 2 * Microblaze MMU emulation for qemu. 3 * 4 * Copyright (c) 2009 Edgar E. Iglesias 5 * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public --- 166 unchanged lines hidden (view full) --- 175 } 176done: 177 D(qemu_log("MMU vaddr=%" PRIx64 " rw=%d tlb_wr=%d tlb_ex=%d hit=%d\n", 178 vaddr, rw, tlb_wr, tlb_ex, hit)); 179 return hit; 180} 181 182/* Writes/reads to the MMU's special regs end up here. */ |
183uint32_t mmu_read(CPUMBState *env, uint32_t rn) | 183uint32_t mmu_read(CPUMBState *env, bool ext, uint32_t rn) |
184{ 185 unsigned int i; 186 uint32_t r = 0; 187 188 if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) { 189 qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n"); 190 return 0; 191 } | 184{ 185 unsigned int i; 186 uint32_t r = 0; 187 188 if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) { 189 qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n"); 190 return 0; 191 } |
192 if (ext && rn != MMU_R_TLBLO) { 193 qemu_log_mask(LOG_GUEST_ERROR, "Extended access only to TLBLO.\n"); 194 return 0; 195 } |
|
192 193 switch (rn) { 194 /* Reads to HI/LO trig reads from the mmu rams. */ 195 case MMU_R_TLBLO: 196 case MMU_R_TLBHI: 197 if (!(env->mmu.c_mmu_tlb_access & 1)) { 198 qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); 199 return 0; 200 } 201 202 i = env->mmu.regs[MMU_R_TLBX] & 0xff; | 196 197 switch (rn) { 198 /* Reads to HI/LO trig reads from the mmu rams. */ 199 case MMU_R_TLBLO: 200 case MMU_R_TLBHI: 201 if (!(env->mmu.c_mmu_tlb_access & 1)) { 202 qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); 203 return 0; 204 } 205 206 i = env->mmu.regs[MMU_R_TLBX] & 0xff; |
203 r = env->mmu.rams[rn & 1][i]; | 207 r = extract64(env->mmu.rams[rn & 1][i], ext * 32, 32); |
204 if (rn == MMU_R_TLBHI) 205 env->mmu.regs[MMU_R_PID] = env->mmu.tids[i]; 206 break; 207 case MMU_R_PID: 208 case MMU_R_ZPR: 209 if (!(env->mmu.c_mmu_tlb_access & 1)) { 210 qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); 211 return 0; --- 9 unchanged lines hidden (view full) --- 221 default: 222 qemu_log_mask(LOG_GUEST_ERROR, "Invalid MMU register %d.\n", rn); 223 break; 224 } 225 D(qemu_log("%s rn=%d=%x\n", __func__, rn, r)); 226 return r; 227} 228 | 208 if (rn == MMU_R_TLBHI) 209 env->mmu.regs[MMU_R_PID] = env->mmu.tids[i]; 210 break; 211 case MMU_R_PID: 212 case MMU_R_ZPR: 213 if (!(env->mmu.c_mmu_tlb_access & 1)) { 214 qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); 215 return 0; --- 9 unchanged lines hidden (view full) --- 225 default: 226 qemu_log_mask(LOG_GUEST_ERROR, "Invalid MMU register %d.\n", rn); 227 break; 228 } 229 D(qemu_log("%s rn=%d=%x\n", __func__, rn, r)); 230 return r; 231} 232 |
229void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v) | 233void mmu_write(CPUMBState *env, bool ext, uint32_t rn, uint32_t v) |
230{ 231 MicroBlazeCPU *cpu = mb_env_get_cpu(env); | 234{ 235 MicroBlazeCPU *cpu = mb_env_get_cpu(env); |
236 uint64_t tmp64; |
|
232 unsigned int i; 233 D(qemu_log("%s rn=%d=%x old=%x\n", __func__, rn, v, env->mmu.regs[rn])); 234 235 if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) { 236 qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n"); 237 return; 238 } | 237 unsigned int i; 238 D(qemu_log("%s rn=%d=%x old=%x\n", __func__, rn, v, env->mmu.regs[rn])); 239 240 if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) { 241 qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n"); 242 return; 243 } |
244 if (ext && rn != MMU_R_TLBLO) { 245 qemu_log_mask(LOG_GUEST_ERROR, "Extended access only to TLBLO.\n"); 246 return; 247 } |
|
239 240 switch (rn) { 241 /* Writes to HI/LO trig writes to the mmu rams. */ 242 case MMU_R_TLBLO: 243 case MMU_R_TLBHI: 244 i = env->mmu.regs[MMU_R_TLBX] & 0xff; 245 if (rn == MMU_R_TLBHI) { 246 if (i < 3 && !(v & TLB_VALID) && qemu_loglevel_mask(~0)) 247 qemu_log_mask(LOG_GUEST_ERROR, 248 "invalidating index %x at pc=%" PRIx64 "\n", 249 i, env->sregs[SR_PC]); 250 env->mmu.tids[i] = env->mmu.regs[MMU_R_PID] & 0xff; 251 mmu_flush_idx(env, i); 252 } | 248 249 switch (rn) { 250 /* Writes to HI/LO trig writes to the mmu rams. */ 251 case MMU_R_TLBLO: 252 case MMU_R_TLBHI: 253 i = env->mmu.regs[MMU_R_TLBX] & 0xff; 254 if (rn == MMU_R_TLBHI) { 255 if (i < 3 && !(v & TLB_VALID) && qemu_loglevel_mask(~0)) 256 qemu_log_mask(LOG_GUEST_ERROR, 257 "invalidating index %x at pc=%" PRIx64 "\n", 258 i, env->sregs[SR_PC]); 259 env->mmu.tids[i] = env->mmu.regs[MMU_R_PID] & 0xff; 260 mmu_flush_idx(env, i); 261 } |
253 env->mmu.rams[rn & 1][i] = v; | 262 tmp64 = env->mmu.rams[rn & 1][i]; 263 env->mmu.rams[rn & 1][i] = deposit64(tmp64, ext * 32, 32, v); |
254 255 D(qemu_log("%s ram[%d][%d]=%x\n", __func__, rn & 1, i, v)); 256 break; 257 case MMU_R_ZPR: 258 if (env->mmu.c_mmu_tlb_access <= 1) { 259 qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); 260 return; 261 } --- 55 unchanged lines hidden --- | 264 265 D(qemu_log("%s ram[%d][%d]=%x\n", __func__, rn & 1, i, v)); 266 break; 267 case MMU_R_ZPR: 268 if (env->mmu.c_mmu_tlb_access <= 1) { 269 qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); 270 return; 271 } --- 55 unchanged lines hidden --- |