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 ---