|
|
1.1 root 1: /*
2: * sparc helpers
1.1.1.4 ! root 3: *
1.1 root 4: * Copyright (c) 2003-2005 Fabrice Bellard
5: *
6: * This library is free software; you can redistribute it and/or
7: * modify it under the terms of the GNU Lesser General Public
8: * License as published by the Free Software Foundation; either
9: * version 2 of the License, or (at your option) any later version.
10: *
11: * This library is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * Lesser General Public License for more details.
15: *
16: * You should have received a copy of the GNU Lesser General Public
17: * License along with this library; if not, write to the Free Software
18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19: */
20: #include <stdarg.h>
21: #include <stdlib.h>
22: #include <stdio.h>
23: #include <string.h>
24: #include <inttypes.h>
25: #include <signal.h>
26: #include <assert.h>
27:
28: #include "cpu.h"
29: #include "exec-all.h"
30:
31: //#define DEBUG_MMU
32:
33: /* Sparc MMU emulation */
34:
35: /* thread support */
36:
37: spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
38:
39: void cpu_lock(void)
40: {
41: spin_lock(&global_cpu_lock);
42: }
43:
44: void cpu_unlock(void)
45: {
46: spin_unlock(&global_cpu_lock);
47: }
48:
1.1.1.4 ! root 49: #if defined(CONFIG_USER_ONLY)
1.1 root 50:
51: int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
1.1.1.4 ! root 52: int mmu_idx, int is_softmmu)
1.1 root 53: {
54: if (rw & 2)
55: env->exception_index = TT_TFAULT;
56: else
57: env->exception_index = TT_DFAULT;
58: return 1;
59: }
60:
61: #else
62:
63: #ifndef TARGET_SPARC64
64: /*
65: * Sparc V8 Reference MMU (SRMMU)
66: */
67: static const int access_table[8][8] = {
68: { 0, 0, 0, 0, 2, 0, 3, 3 },
69: { 0, 0, 0, 0, 2, 0, 0, 0 },
70: { 2, 2, 0, 0, 0, 2, 3, 3 },
71: { 2, 2, 0, 0, 0, 2, 0, 0 },
72: { 2, 0, 2, 0, 2, 2, 3, 3 },
73: { 2, 0, 2, 0, 2, 0, 2, 0 },
74: { 2, 2, 2, 0, 2, 2, 3, 3 },
75: { 2, 2, 2, 0, 2, 2, 2, 0 }
76: };
77:
1.1.1.2 root 78: static const int perm_table[2][8] = {
79: {
80: PAGE_READ,
81: PAGE_READ | PAGE_WRITE,
82: PAGE_READ | PAGE_EXEC,
83: PAGE_READ | PAGE_WRITE | PAGE_EXEC,
84: PAGE_EXEC,
85: PAGE_READ | PAGE_WRITE,
86: PAGE_READ | PAGE_EXEC,
87: PAGE_READ | PAGE_WRITE | PAGE_EXEC
88: },
89: {
90: PAGE_READ,
91: PAGE_READ | PAGE_WRITE,
92: PAGE_READ | PAGE_EXEC,
93: PAGE_READ | PAGE_WRITE | PAGE_EXEC,
94: PAGE_EXEC,
95: PAGE_READ,
96: 0,
97: 0,
98: }
1.1 root 99: };
100:
101: int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
1.1.1.4 ! root 102: int *access_index, target_ulong address, int rw,
! 103: int mmu_idx)
1.1 root 104: {
105: int access_perms = 0;
106: target_phys_addr_t pde_ptr;
107: uint32_t pde;
108: target_ulong virt_addr;
1.1.1.4 ! root 109: int error_code = 0, is_dirty, is_user;
1.1 root 110: unsigned long page_offset;
111:
1.1.1.4 ! root 112: is_user = mmu_idx == MMU_USER_IDX;
1.1 root 113: virt_addr = address & TARGET_PAGE_MASK;
1.1.1.4 ! root 114:
1.1 root 115: if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
1.1.1.4 ! root 116: // Boot mode: instruction fetches are taken from PROM
! 117: if (rw == 2 && (env->mmuregs[0] & env->mmu_bm)) {
! 118: *physical = env->prom_addr | (address & 0x7ffffULL);
! 119: *prot = PAGE_READ | PAGE_EXEC;
! 120: return 0;
! 121: }
! 122: *physical = address;
1.1.1.2 root 123: *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1.1 root 124: return 0;
125: }
126:
127: *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
1.1.1.4 ! root 128: *physical = 0xffffffffffff0000ULL;
1.1 root 129:
130: /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
131: /* Context base + context number */
1.1.1.4 ! root 132: pde_ptr = ((env->mmuregs[1] & ~63)<< 4) + (env->mmuregs[2] << 2);
1.1 root 133: pde = ldl_phys(pde_ptr);
134:
135: /* Ctx pde */
136: switch (pde & PTE_ENTRYTYPE_MASK) {
137: default:
138: case 0: /* Invalid */
1.1.1.4 ! root 139: return 1 << 2;
1.1 root 140: case 2: /* L0 PTE, maybe should not happen? */
141: case 3: /* Reserved */
142: return 4 << 2;
143: case 1: /* L0 PDE */
1.1.1.4 ! root 144: pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
1.1 root 145: pde = ldl_phys(pde_ptr);
146:
1.1.1.4 ! root 147: switch (pde & PTE_ENTRYTYPE_MASK) {
! 148: default:
! 149: case 0: /* Invalid */
! 150: return (1 << 8) | (1 << 2);
! 151: case 3: /* Reserved */
! 152: return (1 << 8) | (4 << 2);
! 153: case 1: /* L1 PDE */
! 154: pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
1.1 root 155: pde = ldl_phys(pde_ptr);
156:
1.1.1.4 ! root 157: switch (pde & PTE_ENTRYTYPE_MASK) {
! 158: default:
! 159: case 0: /* Invalid */
! 160: return (2 << 8) | (1 << 2);
! 161: case 3: /* Reserved */
! 162: return (2 << 8) | (4 << 2);
! 163: case 1: /* L2 PDE */
! 164: pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
1.1 root 165: pde = ldl_phys(pde_ptr);
166:
1.1.1.4 ! root 167: switch (pde & PTE_ENTRYTYPE_MASK) {
! 168: default:
! 169: case 0: /* Invalid */
! 170: return (3 << 8) | (1 << 2);
! 171: case 1: /* PDE, should not happen */
! 172: case 3: /* Reserved */
! 173: return (3 << 8) | (4 << 2);
! 174: case 2: /* L3 PTE */
! 175: virt_addr = address & TARGET_PAGE_MASK;
! 176: page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
! 177: }
! 178: break;
! 179: case 2: /* L2 PTE */
! 180: virt_addr = address & ~0x3ffff;
! 181: page_offset = address & 0x3ffff;
! 182: }
! 183: break;
! 184: case 2: /* L1 PTE */
! 185: virt_addr = address & ~0xffffff;
! 186: page_offset = address & 0xffffff;
! 187: }
1.1 root 188: }
189:
190: /* update page modified and dirty bits */
191: is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
192: if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
1.1.1.4 ! root 193: pde |= PG_ACCESSED_MASK;
! 194: if (is_dirty)
! 195: pde |= PG_MODIFIED_MASK;
1.1 root 196: stl_phys_notdirty(pde_ptr, pde);
197: }
198: /* check access */
199: access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
200: error_code = access_table[*access_index][access_perms];
1.1.1.3 root 201: if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
1.1.1.4 ! root 202: return error_code;
1.1 root 203:
204: /* the page can be put in the TLB */
1.1.1.2 root 205: *prot = perm_table[is_user][access_perms];
206: if (!(pde & PG_MODIFIED_MASK)) {
1.1 root 207: /* only set write access if already dirty... otherwise wait
208: for dirty access */
1.1.1.2 root 209: *prot &= ~PAGE_WRITE;
1.1 root 210: }
211:
212: /* Even if large ptes, we map only one 4KB page in the cache to
213: avoid filling it too fast */
1.1.1.4 ! root 214: *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
1.1 root 215: return error_code;
216: }
217:
218: /* Perform address translation */
219: int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1.1.1.4 ! root 220: int mmu_idx, int is_softmmu)
1.1 root 221: {
222: target_phys_addr_t paddr;
1.1.1.4 ! root 223: target_ulong vaddr;
1.1 root 224: int error_code = 0, prot, ret = 0, access_index;
225:
1.1.1.4 ! root 226: error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, mmu_idx);
1.1 root 227: if (error_code == 0) {
1.1.1.4 ! root 228: vaddr = address & TARGET_PAGE_MASK;
! 229: paddr &= TARGET_PAGE_MASK;
1.1.1.2 root 230: #ifdef DEBUG_MMU
1.1.1.4 ! root 231: printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
! 232: TARGET_FMT_lx "\n", address, paddr, vaddr);
1.1.1.2 root 233: #endif
1.1.1.4 ! root 234: ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
! 235: return ret;
1.1 root 236: }
237:
238: if (env->mmuregs[3]) /* Fault status register */
1.1.1.4 ! root 239: env->mmuregs[3] = 1; /* overflow (not read before another fault) */
1.1 root 240: env->mmuregs[3] |= (access_index << 5) | error_code | 2;
241: env->mmuregs[4] = address; /* Fault address register */
242:
243: if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
244: // No fault mode: if a mapping is available, just override
245: // permissions. If no mapping is available, redirect accesses to
246: // neverland. Fake/overridden mappings will be flushed when
247: // switching to normal mode.
1.1.1.4 ! root 248: vaddr = address & TARGET_PAGE_MASK;
1.1.1.2 root 249: prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1.1.1.4 ! root 250: ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
! 251: return ret;
1.1 root 252: } else {
253: if (rw & 2)
254: env->exception_index = TT_TFAULT;
255: else
256: env->exception_index = TT_DFAULT;
257: return 1;
258: }
259: }
1.1.1.2 root 260:
261: target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
262: {
263: target_phys_addr_t pde_ptr;
264: uint32_t pde;
265:
266: /* Context base + context number */
1.1.1.4 ! root 267: pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
! 268: (env->mmuregs[2] << 2);
1.1.1.2 root 269: pde = ldl_phys(pde_ptr);
270:
271: switch (pde & PTE_ENTRYTYPE_MASK) {
272: default:
273: case 0: /* Invalid */
274: case 2: /* PTE, maybe should not happen? */
275: case 3: /* Reserved */
1.1.1.4 ! root 276: return 0;
1.1.1.2 root 277: case 1: /* L1 PDE */
1.1.1.4 ! root 278: if (mmulev == 3)
! 279: return pde;
! 280: pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
1.1.1.2 root 281: pde = ldl_phys(pde_ptr);
282:
1.1.1.4 ! root 283: switch (pde & PTE_ENTRYTYPE_MASK) {
! 284: default:
! 285: case 0: /* Invalid */
! 286: case 3: /* Reserved */
! 287: return 0;
! 288: case 2: /* L1 PTE */
! 289: return pde;
! 290: case 1: /* L2 PDE */
! 291: if (mmulev == 2)
! 292: return pde;
! 293: pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
1.1.1.2 root 294: pde = ldl_phys(pde_ptr);
295:
1.1.1.4 ! root 296: switch (pde & PTE_ENTRYTYPE_MASK) {
! 297: default:
! 298: case 0: /* Invalid */
! 299: case 3: /* Reserved */
! 300: return 0;
! 301: case 2: /* L2 PTE */
! 302: return pde;
! 303: case 1: /* L3 PDE */
! 304: if (mmulev == 1)
! 305: return pde;
! 306: pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
1.1.1.2 root 307: pde = ldl_phys(pde_ptr);
308:
1.1.1.4 ! root 309: switch (pde & PTE_ENTRYTYPE_MASK) {
! 310: default:
! 311: case 0: /* Invalid */
! 312: case 1: /* PDE, should not happen */
! 313: case 3: /* Reserved */
! 314: return 0;
! 315: case 2: /* L3 PTE */
! 316: return pde;
! 317: }
! 318: }
! 319: }
1.1.1.2 root 320: }
321: return 0;
322: }
323:
324: #ifdef DEBUG_MMU
325: void dump_mmu(CPUState *env)
326: {
1.1.1.4 ! root 327: target_ulong va, va1, va2;
! 328: unsigned int n, m, o;
! 329: target_phys_addr_t pde_ptr, pa;
1.1.1.2 root 330: uint32_t pde;
331:
332: printf("MMU dump:\n");
333: pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
334: pde = ldl_phys(pde_ptr);
1.1.1.4 ! root 335: printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
! 336: (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
1.1.1.2 root 337: for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
1.1.1.4 ! root 338: pde = mmu_probe(env, va, 2);
! 339: if (pde) {
! 340: pa = cpu_get_phys_page_debug(env, va);
! 341: printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
! 342: " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
! 343: for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
! 344: pde = mmu_probe(env, va1, 1);
! 345: if (pde) {
! 346: pa = cpu_get_phys_page_debug(env, va1);
! 347: printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
! 348: " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
! 349: for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
! 350: pde = mmu_probe(env, va2, 0);
! 351: if (pde) {
! 352: pa = cpu_get_phys_page_debug(env, va2);
! 353: printf(" VA: " TARGET_FMT_lx ", PA: "
! 354: TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
! 355: va2, pa, pde);
! 356: }
! 357: }
! 358: }
! 359: }
! 360: }
1.1.1.2 root 361: }
362: printf("MMU dump ends\n");
363: }
364: #endif /* DEBUG_MMU */
365:
366: #else /* !TARGET_SPARC64 */
1.1 root 367: /*
368: * UltraSparc IIi I/DMMUs
369: */
370: static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot,
1.1.1.4 ! root 371: int *access_index, target_ulong address, int rw,
! 372: int is_user)
1.1 root 373: {
374: target_ulong mask;
375: unsigned int i;
376:
377: if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
1.1.1.4 ! root 378: *physical = address;
! 379: *prot = PAGE_READ | PAGE_WRITE;
1.1 root 380: return 0;
381: }
382:
383: for (i = 0; i < 64; i++) {
1.1.1.4 ! root 384: switch ((env->dtlb_tte[i] >> 61) & 3) {
! 385: default:
! 386: case 0x0: // 8k
! 387: mask = 0xffffffffffffe000ULL;
! 388: break;
! 389: case 0x1: // 64k
! 390: mask = 0xffffffffffff0000ULL;
! 391: break;
! 392: case 0x2: // 512k
! 393: mask = 0xfffffffffff80000ULL;
! 394: break;
! 395: case 0x3: // 4M
! 396: mask = 0xffffffffffc00000ULL;
! 397: break;
! 398: }
! 399: // ctx match, vaddr match?
! 400: if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
! 401: (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
! 402: // valid, access ok?
! 403: if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
! 404: ((env->dtlb_tte[i] & 0x4) && is_user) ||
! 405: (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
! 406: if (env->dmmuregs[3]) /* Fault status register */
! 407: env->dmmuregs[3] = 2; /* overflow (not read before another fault) */
! 408: env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
! 409: env->dmmuregs[4] = address; /* Fault address register */
! 410: env->exception_index = TT_DFAULT;
1.1 root 411: #ifdef DEBUG_MMU
1.1.1.4 ! root 412: printf("DFAULT at 0x%" PRIx64 "\n", address);
1.1 root 413: #endif
1.1.1.4 ! root 414: return 1;
! 415: }
! 416: *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
! 417: *prot = PAGE_READ;
! 418: if (env->dtlb_tte[i] & 0x2)
! 419: *prot |= PAGE_WRITE;
! 420: return 0;
! 421: }
1.1 root 422: }
423: #ifdef DEBUG_MMU
1.1.1.3 root 424: printf("DMISS at 0x%" PRIx64 "\n", address);
1.1 root 425: #endif
426: env->exception_index = TT_DMISS;
427: return 1;
428: }
429:
430: static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical, int *prot,
1.1.1.4 ! root 431: int *access_index, target_ulong address, int rw,
! 432: int is_user)
1.1 root 433: {
434: target_ulong mask;
435: unsigned int i;
436:
437: if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
1.1.1.4 ! root 438: *physical = address;
! 439: *prot = PAGE_EXEC;
1.1 root 440: return 0;
441: }
442:
443: for (i = 0; i < 64; i++) {
1.1.1.4 ! root 444: switch ((env->itlb_tte[i] >> 61) & 3) {
! 445: default:
! 446: case 0x0: // 8k
! 447: mask = 0xffffffffffffe000ULL;
! 448: break;
! 449: case 0x1: // 64k
! 450: mask = 0xffffffffffff0000ULL;
! 451: break;
! 452: case 0x2: // 512k
! 453: mask = 0xfffffffffff80000ULL;
! 454: break;
! 455: case 0x3: // 4M
! 456: mask = 0xffffffffffc00000ULL;
! 457: break;
! 458: }
! 459: // ctx match, vaddr match?
! 460: if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
! 461: (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
! 462: // valid, access ok?
! 463: if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
! 464: ((env->itlb_tte[i] & 0x4) && is_user)) {
! 465: if (env->immuregs[3]) /* Fault status register */
! 466: env->immuregs[3] = 2; /* overflow (not read before another fault) */
! 467: env->immuregs[3] |= (is_user << 3) | 1;
! 468: env->exception_index = TT_TFAULT;
1.1 root 469: #ifdef DEBUG_MMU
1.1.1.4 ! root 470: printf("TFAULT at 0x%" PRIx64 "\n", address);
1.1 root 471: #endif
1.1.1.4 ! root 472: return 1;
! 473: }
! 474: *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
! 475: *prot = PAGE_EXEC;
! 476: return 0;
! 477: }
1.1 root 478: }
479: #ifdef DEBUG_MMU
1.1.1.3 root 480: printf("TMISS at 0x%" PRIx64 "\n", address);
1.1 root 481: #endif
482: env->exception_index = TT_TMISS;
483: return 1;
484: }
485:
486: int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot,
1.1.1.4 ! root 487: int *access_index, target_ulong address, int rw,
! 488: int mmu_idx)
1.1 root 489: {
1.1.1.4 ! root 490: int is_user = mmu_idx == MMU_USER_IDX;
! 491:
1.1 root 492: if (rw == 2)
1.1.1.4 ! root 493: return get_physical_address_code(env, physical, prot, access_index, address, rw, is_user);
1.1 root 494: else
1.1.1.4 ! root 495: return get_physical_address_data(env, physical, prot, access_index, address, rw, is_user);
1.1 root 496: }
497:
498: /* Perform address translation */
499: int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1.1.1.4 ! root 500: int mmu_idx, int is_softmmu)
1.1 root 501: {
502: target_ulong virt_addr, vaddr;
503: target_phys_addr_t paddr;
504: int error_code = 0, prot, ret = 0, access_index;
505:
1.1.1.4 ! root 506: error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, mmu_idx);
1.1 root 507: if (error_code == 0) {
1.1.1.4 ! root 508: virt_addr = address & TARGET_PAGE_MASK;
! 509: vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
1.1 root 510: #ifdef DEBUG_MMU
1.1.1.4 ! root 511: printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64 "\n", address, paddr, vaddr);
1.1 root 512: #endif
1.1.1.4 ! root 513: ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
! 514: return ret;
1.1 root 515: }
516: // XXX
517: return 1;
518: }
519:
520: #ifdef DEBUG_MMU
521: void dump_mmu(CPUState *env)
522: {
523: unsigned int i;
524: const char *mask;
525:
1.1.1.3 root 526: printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n", env->dmmuregs[1], env->dmmuregs[2]);
1.1 root 527: if ((env->lsu & DMMU_E) == 0) {
1.1.1.4 ! root 528: printf("DMMU disabled\n");
1.1 root 529: } else {
1.1.1.4 ! root 530: printf("DMMU dump:\n");
! 531: for (i = 0; i < 64; i++) {
! 532: switch ((env->dtlb_tte[i] >> 61) & 3) {
! 533: default:
! 534: case 0x0:
! 535: mask = " 8k";
! 536: break;
! 537: case 0x1:
! 538: mask = " 64k";
! 539: break;
! 540: case 0x2:
! 541: mask = "512k";
! 542: break;
! 543: case 0x3:
! 544: mask = " 4M";
! 545: break;
! 546: }
! 547: if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
! 548: printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, %s, ctx %" PRId64 "\n",
! 549: env->dtlb_tag[i] & ~0x1fffULL,
! 550: env->dtlb_tte[i] & 0x1ffffffe000ULL,
! 551: mask,
! 552: env->dtlb_tte[i] & 0x4? "priv": "user",
! 553: env->dtlb_tte[i] & 0x2? "RW": "RO",
! 554: env->dtlb_tte[i] & 0x40? "locked": "unlocked",
! 555: env->dtlb_tag[i] & 0x1fffULL);
! 556: }
! 557: }
1.1 root 558: }
559: if ((env->lsu & IMMU_E) == 0) {
1.1.1.4 ! root 560: printf("IMMU disabled\n");
1.1 root 561: } else {
1.1.1.4 ! root 562: printf("IMMU dump:\n");
! 563: for (i = 0; i < 64; i++) {
! 564: switch ((env->itlb_tte[i] >> 61) & 3) {
! 565: default:
! 566: case 0x0:
! 567: mask = " 8k";
! 568: break;
! 569: case 0x1:
! 570: mask = " 64k";
! 571: break;
! 572: case 0x2:
! 573: mask = "512k";
! 574: break;
! 575: case 0x3:
! 576: mask = " 4M";
! 577: break;
! 578: }
! 579: if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
! 580: printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, ctx %" PRId64 "\n",
! 581: env->itlb_tag[i] & ~0x1fffULL,
! 582: env->itlb_tte[i] & 0x1ffffffe000ULL,
! 583: mask,
! 584: env->itlb_tte[i] & 0x4? "priv": "user",
! 585: env->itlb_tte[i] & 0x40? "locked": "unlocked",
! 586: env->itlb_tag[i] & 0x1fffULL);
! 587: }
! 588: }
1.1 root 589: }
590: }
1.1.1.2 root 591: #endif /* DEBUG_MMU */
592:
593: #endif /* TARGET_SPARC64 */
594: #endif /* !CONFIG_USER_ONLY */
595:
596: void memcpy32(target_ulong *dst, const target_ulong *src)
597: {
598: dst[0] = src[0];
599: dst[1] = src[1];
600: dst[2] = src[2];
601: dst[3] = src[3];
602: dst[4] = src[4];
603: dst[5] = src[5];
604: dst[6] = src[6];
605: dst[7] = src[7];
606: }
1.1.1.4 ! root 607:
! 608: #ifdef TARGET_SPARC64
! 609: #if !defined(CONFIG_USER_ONLY)
! 610: #include "qemu-common.h"
! 611: #include "hw/irq.h"
! 612: #include "qemu-timer.h"
! 613: #endif
! 614:
! 615: void do_tick_set_count(void *opaque, uint64_t count)
! 616: {
! 617: #if !defined(CONFIG_USER_ONLY)
! 618: ptimer_set_count(opaque, -count);
! 619: #endif
! 620: }
! 621:
! 622: uint64_t do_tick_get_count(void *opaque)
! 623: {
! 624: #if !defined(CONFIG_USER_ONLY)
! 625: return -ptimer_get_count(opaque);
! 626: #else
! 627: return 0;
! 628: #endif
! 629: }
! 630:
! 631: void do_tick_set_limit(void *opaque, uint64_t limit)
! 632: {
! 633: #if !defined(CONFIG_USER_ONLY)
! 634: ptimer_set_limit(opaque, -limit, 0);
! 635: #endif
! 636: }
! 637: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.