helper.c 15.5 KB
Newer Older
1 2 3
/*
 *  sparc helpers
 * 
bellard's avatar
bellard committed
4
 *  Copyright (c) 2003-2005 Fabrice Bellard
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
20 21 22 23 24 25 26 27 28 29
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <signal.h>
#include <assert.h>

#include "cpu.h"
#include "exec-all.h"
30

bellard's avatar
bellard committed
31
//#define DEBUG_MMU
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

/* Sparc MMU emulation */

/* thread support */

spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;

void cpu_lock(void)
{
    spin_lock(&global_cpu_lock);
}

void cpu_unlock(void)
{
    spin_unlock(&global_cpu_lock);
}

bellard's avatar
bellard committed
49 50 51 52 53
#if defined(CONFIG_USER_ONLY) 

int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
                               int is_user, int is_softmmu)
{
bellard's avatar
bellard committed
54 55 56 57
    if (rw & 2)
        env->exception_index = TT_TFAULT;
    else
        env->exception_index = TT_DFAULT;
bellard's avatar
bellard committed
58 59 60 61
    return 1;
}

#else
62

bellard's avatar
bellard committed
63
#ifndef TARGET_SPARC64
bellard's avatar
bellard committed
64 65 66
/*
 * Sparc V8 Reference MMU (SRMMU)
 */
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
static const int access_table[8][8] = {
    { 0, 0, 0, 0, 2, 0, 3, 3 },
    { 0, 0, 0, 0, 2, 0, 0, 0 },
    { 2, 2, 0, 0, 0, 2, 3, 3 },
    { 2, 2, 0, 0, 0, 2, 0, 0 },
    { 2, 0, 2, 0, 2, 2, 3, 3 },
    { 2, 0, 2, 0, 2, 0, 2, 0 },
    { 2, 2, 2, 0, 2, 2, 3, 3 },
    { 2, 2, 2, 0, 2, 2, 2, 0 }
};

/* 1 = write OK */
static const int rw_table[2][8] = {
    { 0, 1, 0, 1, 0, 1, 0, 1 },
    { 0, 1, 0, 1, 0, 0, 0, 0 }
};

84 85
int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
			  int *access_index, target_ulong address, int rw,
bellard's avatar
bellard committed
86
			  int is_user)
87
{
bellard's avatar
bellard committed
88 89
    int access_perms = 0;
    target_phys_addr_t pde_ptr;
90 91
    uint32_t pde;
    target_ulong virt_addr;
bellard's avatar
bellard committed
92 93
    int error_code = 0, is_dirty;
    unsigned long page_offset;
94 95 96

    virt_addr = address & TARGET_PAGE_MASK;
    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
bellard's avatar
bellard committed
97 98 99
	*physical = address;
        *prot = PAGE_READ | PAGE_WRITE;
        return 0;
100 101
    }

bellard's avatar
bellard committed
102
    *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
bellard's avatar
bellard committed
103
    *physical = 0xfffff000;
bellard's avatar
bellard committed
104

105 106
    /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
    /* Context base + context number */
bellard's avatar
bellard committed
107
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
bellard's avatar
bellard committed
108
    pde = ldl_phys(pde_ptr);
109 110 111

    /* Ctx pde */
    switch (pde & PTE_ENTRYTYPE_MASK) {
bellard's avatar
bellard committed
112
    default:
113
    case 0: /* Invalid */
bellard's avatar
bellard committed
114
	return 1 << 2;
bellard's avatar
bellard committed
115
    case 2: /* L0 PTE, maybe should not happen? */
116
    case 3: /* Reserved */
bellard's avatar
bellard committed
117
        return 4 << 2;
bellard's avatar
bellard committed
118 119
    case 1: /* L0 PDE */
	pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
bellard's avatar
bellard committed
120
        pde = ldl_phys(pde_ptr);
121 122

	switch (pde & PTE_ENTRYTYPE_MASK) {
bellard's avatar
bellard committed
123
	default:
124
	case 0: /* Invalid */
bellard's avatar
bellard committed
125
	    return (1 << 8) | (1 << 2);
126
	case 3: /* Reserved */
bellard's avatar
bellard committed
127
	    return (1 << 8) | (4 << 2);
bellard's avatar
bellard committed
128 129
	case 1: /* L1 PDE */
	    pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
bellard's avatar
bellard committed
130
            pde = ldl_phys(pde_ptr);
131 132

	    switch (pde & PTE_ENTRYTYPE_MASK) {
bellard's avatar
bellard committed
133
	    default:
134
	    case 0: /* Invalid */
bellard's avatar
bellard committed
135
		return (2 << 8) | (1 << 2);
136
	    case 3: /* Reserved */
bellard's avatar
bellard committed
137
		return (2 << 8) | (4 << 2);
bellard's avatar
bellard committed
138 139
	    case 1: /* L2 PDE */
		pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
bellard's avatar
bellard committed
140
                pde = ldl_phys(pde_ptr);
141 142

		switch (pde & PTE_ENTRYTYPE_MASK) {
bellard's avatar
bellard committed
143
		default:
144
		case 0: /* Invalid */
bellard's avatar
bellard committed
145
		    return (3 << 8) | (1 << 2);
146 147
		case 1: /* PDE, should not happen */
		case 3: /* Reserved */
bellard's avatar
bellard committed
148
		    return (3 << 8) | (4 << 2);
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
		case 2: /* L3 PTE */
		    virt_addr = address & TARGET_PAGE_MASK;
		    page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
		}
		break;
	    case 2: /* L2 PTE */
		virt_addr = address & ~0x3ffff;
		page_offset = address & 0x3ffff;
	    }
	    break;
	case 2: /* L1 PTE */
	    virt_addr = address & ~0xffffff;
	    page_offset = address & 0xffffff;
	}
    }

    /* update page modified and dirty bits */
bellard's avatar
bellard committed
166
    is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
167 168 169 170
    if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
	pde |= PG_ACCESSED_MASK;
	if (is_dirty)
	    pde |= PG_MODIFIED_MASK;
bellard's avatar
bellard committed
171
        stl_phys_notdirty(pde_ptr, pde);
172 173 174
    }
    /* check access */
    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
bellard's avatar
bellard committed
175
    error_code = access_table[*access_index][access_perms];
bellard's avatar
bellard committed
176
    if (error_code && !(env->mmuregs[0] & MMU_NF))
bellard's avatar
bellard committed
177
	return error_code;
178 179

    /* the page can be put in the TLB */
bellard's avatar
bellard committed
180
    *prot = PAGE_READ;
181 182 183 184
    if (pde & PG_MODIFIED_MASK) {
        /* only set write access if already dirty... otherwise wait
           for dirty access */
	if (rw_table[is_user][access_perms])
bellard's avatar
bellard committed
185
	        *prot |= PAGE_WRITE;
186 187 188 189
    }

    /* Even if large ptes, we map only one 4KB page in the cache to
       avoid filling it too fast */
bellard's avatar
bellard committed
190
    *physical = ((pde & PTE_ADDR_MASK) << 4) + page_offset;
bellard's avatar
bellard committed
191
    return error_code;
bellard's avatar
bellard committed
192 193 194
}

/* Perform address translation */
195
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
bellard's avatar
bellard committed
196 197
                              int is_user, int is_softmmu)
{
198 199
    target_ulong virt_addr;
    target_phys_addr_t paddr;
bellard's avatar
bellard committed
200 201
    unsigned long vaddr;
    int error_code = 0, prot, ret = 0, access_index;
202

bellard's avatar
bellard committed
203 204 205 206 207 208 209
    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
    if (error_code == 0) {
	virt_addr = address & TARGET_PAGE_MASK;
	vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
	ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
	return ret;
    }
210 211 212

    if (env->mmuregs[3]) /* Fault status register */
	env->mmuregs[3] = 1; /* overflow (not read before another fault) */
bellard's avatar
bellard committed
213
    env->mmuregs[3] |= (access_index << 5) | error_code | 2;
214 215
    env->mmuregs[4] = address; /* Fault address register */

bellard's avatar
bellard committed
216
    if ((env->mmuregs[0] & MMU_NF) || env->psret == 0)  {
bellard's avatar
bellard committed
217 218 219 220
        // No fault mode: if a mapping is available, just override
        // permissions. If no mapping is available, redirect accesses to
        // neverland. Fake/overridden mappings will be flushed when
        // switching to normal mode.
bellard's avatar
bellard committed
221 222 223 224 225 226 227 228 229 230
	vaddr = address & TARGET_PAGE_MASK;
        prot = PAGE_READ | PAGE_WRITE;
        ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
	return ret;
    } else {
        if (rw & 2)
            env->exception_index = TT_TFAULT;
        else
            env->exception_index = TT_DFAULT;
        return 1;
bellard's avatar
bellard committed
231
    }
232
}
bellard's avatar
bellard committed
233
#else
bellard's avatar
bellard committed
234 235 236
/*
 * UltraSparc IIi I/DMMUs
 */
bellard's avatar
bellard committed
237 238 239 240 241 242 243 244
static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot,
			  int *access_index, target_ulong address, int rw,
			  int is_user)
{
    target_ulong mask;
    unsigned int i;

    if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
bellard's avatar
bellard committed
245
	*physical = address;
bellard's avatar
bellard committed
246 247 248 249 250
	*prot = PAGE_READ | PAGE_WRITE;
        return 0;
    }

    for (i = 0; i < 64; i++) {
bellard's avatar
bellard committed
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
	switch ((env->dtlb_tte[i] >> 61) & 3) {
	default:
	case 0x0: // 8k
	    mask = 0xffffffffffffe000ULL;
	    break;
	case 0x1: // 64k
	    mask = 0xffffffffffff0000ULL;
	    break;
	case 0x2: // 512k
	    mask = 0xfffffffffff80000ULL;
	    break;
	case 0x3: // 4M
	    mask = 0xffffffffffc00000ULL;
	    break;
	}
	// ctx match, vaddr match?
	if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
	    (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
	    // valid, access ok?
	    if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
		((env->dtlb_tte[i] & 0x4) && is_user) ||
		(!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
		if (env->dmmuregs[3]) /* Fault status register */
		    env->dmmuregs[3] = 2; /* overflow (not read before another fault) */
		env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
		env->dmmuregs[4] = address; /* Fault address register */
		env->exception_index = TT_DFAULT;
#ifdef DEBUG_MMU
		printf("DFAULT at 0x%llx\n", address);
#endif
		return 1;
bellard's avatar
bellard committed
282
	    }
bellard's avatar
bellard committed
283 284 285 286 287
	    *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
	    *prot = PAGE_READ;
	    if (env->dtlb_tte[i] & 0x2)
		*prot |= PAGE_WRITE;
	    return 0;
bellard's avatar
bellard committed
288 289
	}
    }
bellard's avatar
bellard committed
290 291 292 293
#ifdef DEBUG_MMU
    printf("DMISS at 0x%llx\n", address);
#endif
    env->exception_index = TT_DMISS;
bellard's avatar
bellard committed
294 295 296 297 298 299 300 301 302 303 304
    return 1;
}

static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical, int *prot,
			  int *access_index, target_ulong address, int rw,
			  int is_user)
{
    target_ulong mask;
    unsigned int i;

    if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
bellard's avatar
bellard committed
305
	*physical = address;
bellard's avatar
bellard committed
306 307 308
	*prot = PAGE_READ;
        return 0;
    }
bellard's avatar
bellard committed
309

bellard's avatar
bellard committed
310
    for (i = 0; i < 64; i++) {
bellard's avatar
bellard committed
311 312 313 314 315 316 317 318 319 320 321 322 323
	switch ((env->itlb_tte[i] >> 61) & 3) {
	default:
	case 0x0: // 8k
	    mask = 0xffffffffffffe000ULL;
	    break;
	case 0x1: // 64k
	    mask = 0xffffffffffff0000ULL;
	    break;
	case 0x2: // 512k
	    mask = 0xfffffffffff80000ULL;
	    break;
	case 0x3: // 4M
	    mask = 0xffffffffffc00000ULL;
bellard's avatar
bellard committed
324
		break;
bellard's avatar
bellard committed
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
	}
	// ctx match, vaddr match?
	if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
	    (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
	    // valid, access ok?
	    if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
		((env->itlb_tte[i] & 0x4) && is_user)) {
		if (env->immuregs[3]) /* Fault status register */
		    env->immuregs[3] = 2; /* overflow (not read before another fault) */
		env->immuregs[3] |= (is_user << 3) | 1;
		env->exception_index = TT_TFAULT;
#ifdef DEBUG_MMU
		printf("TFAULT at 0x%llx\n", address);
#endif
		return 1;
bellard's avatar
bellard committed
340
	    }
bellard's avatar
bellard committed
341 342 343
	    *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
	    *prot = PAGE_READ;
	    return 0;
bellard's avatar
bellard committed
344 345
	}
    }
bellard's avatar
bellard committed
346 347 348 349
#ifdef DEBUG_MMU
    printf("TMISS at 0x%llx\n", address);
#endif
    env->exception_index = TT_TMISS;
bellard's avatar
bellard committed
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
    return 1;
}

int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot,
			  int *access_index, target_ulong address, int rw,
			  int is_user)
{
    if (rw == 2)
	return get_physical_address_code(env, physical, prot, access_index, address, rw, is_user);
    else
	return get_physical_address_data(env, physical, prot, access_index, address, rw, is_user);
}

/* Perform address translation */
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                              int is_user, int is_softmmu)
{
bellard's avatar
bellard committed
367
    target_ulong virt_addr, vaddr;
bellard's avatar
bellard committed
368 369 370 371 372 373 374
    target_phys_addr_t paddr;
    int error_code = 0, prot, ret = 0, access_index;

    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
    if (error_code == 0) {
	virt_addr = address & TARGET_PAGE_MASK;
	vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
bellard's avatar
bellard committed
375 376 377
#ifdef DEBUG_MMU
	printf("Translate at 0x%llx -> 0x%llx, vaddr 0x%llx\n", address, paddr, vaddr);
#endif
bellard's avatar
bellard committed
378 379 380 381 382 383 384 385
	ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
	return ret;
    }
    // XXX
    return 1;
}

#endif
bellard's avatar
bellard committed
386
#endif
387

388
void memcpy32(target_ulong *dst, const target_ulong *src)
389 390 391 392 393 394 395 396 397 398 399
{
    dst[0] = src[0];
    dst[1] = src[1];
    dst[2] = src[2];
    dst[3] = src[3];
    dst[4] = src[4];
    dst[5] = src[5];
    dst[6] = src[6];
    dst[7] = src[7];
}

400 401
#if !defined(TARGET_SPARC64)
target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
bellard's avatar
bellard committed
402 403 404 405 406
{
    target_phys_addr_t pde_ptr;
    uint32_t pde;

    /* Context base + context number */
bellard's avatar
bellard committed
407
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
bellard's avatar
bellard committed
408 409
    pde = ldl_phys(pde_ptr);

bellard's avatar
bellard committed
410 411 412 413 414 415 416 417 418 419
    switch (pde & PTE_ENTRYTYPE_MASK) {
    default:
    case 0: /* Invalid */
    case 2: /* PTE, maybe should not happen? */
    case 3: /* Reserved */
	return 0;
    case 1: /* L1 PDE */
	if (mmulev == 3)
	    return pde;
	pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
bellard's avatar
bellard committed
420
        pde = ldl_phys(pde_ptr);
bellard's avatar
bellard committed
421 422 423 424 425 426 427 428 429 430 431 432

	switch (pde & PTE_ENTRYTYPE_MASK) {
	default:
	case 0: /* Invalid */
	case 3: /* Reserved */
	    return 0;
	case 2: /* L1 PTE */
	    return pde;
	case 1: /* L2 PDE */
	    if (mmulev == 2)
		return pde;
	    pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
bellard's avatar
bellard committed
433
            pde = ldl_phys(pde_ptr);
bellard's avatar
bellard committed
434 435 436 437 438 439 440 441 442 443 444 445

	    switch (pde & PTE_ENTRYTYPE_MASK) {
	    default:
	    case 0: /* Invalid */
	    case 3: /* Reserved */
		return 0;
	    case 2: /* L2 PTE */
		return pde;
	    case 1: /* L3 PDE */
		if (mmulev == 1)
		    return pde;
		pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
bellard's avatar
bellard committed
446
                pde = ldl_phys(pde_ptr);
bellard's avatar
bellard committed
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462

		switch (pde & PTE_ENTRYTYPE_MASK) {
		default:
		case 0: /* Invalid */
		case 1: /* PDE, should not happen */
		case 3: /* Reserved */
		    return 0;
		case 2: /* L3 PTE */
		    return pde;
		}
	    }
	}
    }
    return 0;
}

bellard's avatar
bellard committed
463
#ifdef DEBUG_MMU
464
void dump_mmu(CPUState *env)
bellard's avatar
bellard committed
465
{
466 467 468
     target_ulong va, va1, va2;
     unsigned int n, m, o;
     target_phys_addr_t pde_ptr, pa;
bellard's avatar
bellard committed
469 470 471
    uint32_t pde;

    printf("MMU dump:\n");
bellard's avatar
bellard committed
472
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
bellard's avatar
bellard committed
473
    pde = ldl_phys(pde_ptr);
474
    printf("Root ptr: " TARGET_FMT_lx ", ctx: %d\n", env->mmuregs[1] << 4, env->mmuregs[2]);
bellard's avatar
bellard committed
475
    for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
476
	pde_ptr = mmu_probe(env, va, 2);
bellard's avatar
bellard committed
477 478
	if (pde_ptr) {
	    pa = cpu_get_phys_page_debug(env, va);
479
 	    printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va, pa, pde_ptr);
bellard's avatar
bellard committed
480
	    for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
481
		pde_ptr = mmu_probe(env, va1, 1);
bellard's avatar
bellard committed
482 483
		if (pde_ptr) {
		    pa = cpu_get_phys_page_debug(env, va1);
484
 		    printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va1, pa, pde_ptr);
bellard's avatar
bellard committed
485
		    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
486
			pde_ptr = mmu_probe(env, va2, 0);
bellard's avatar
bellard committed
487 488
			if (pde_ptr) {
			    pa = cpu_get_phys_page_debug(env, va2);
489
 			    printf("  VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PTE: " TARGET_FMT_lx "\n", va2, pa, pde_ptr);
bellard's avatar
bellard committed
490 491 492 493 494 495 496 497
			}
		    }
		}
	    }
	}
    }
    printf("MMU dump ends\n");
}
bellard's avatar
bellard committed
498
#endif
bellard's avatar
bellard committed
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
#else
#ifdef DEBUG_MMU
void dump_mmu(CPUState *env)
{
    unsigned int i;
    const char *mask;

    printf("MMU contexts: Primary: %lld, Secondary: %lld\n", env->dmmuregs[1], env->dmmuregs[2]);
    if ((env->lsu & DMMU_E) == 0) {
	printf("DMMU disabled\n");
    } else {
	printf("DMMU dump:\n");
	for (i = 0; i < 64; i++) {
	    switch ((env->dtlb_tte[i] >> 61) & 3) {
	    default:
	    case 0x0:
		mask = "  8k";
		break;
	    case 0x1:
		mask = " 64k";
		break;
	    case 0x2:
		mask = "512k";
		break;
	    case 0x3:
		mask = "  4M";
		break;
	    }
	    if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
		printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, %s, ctx %lld\n",
		       env->dtlb_tag[i] & ~0x1fffULL,
		       env->dtlb_tte[i] & 0x1ffffffe000ULL,
		       mask,
		       env->dtlb_tte[i] & 0x4? "priv": "user",
		       env->dtlb_tte[i] & 0x2? "RW": "RO",
		       env->dtlb_tte[i] & 0x40? "locked": "unlocked",
		       env->dtlb_tag[i] & 0x1fffULL);
	    }
	}
    }
    if ((env->lsu & IMMU_E) == 0) {
	printf("IMMU disabled\n");
    } else {
	printf("IMMU dump:\n");
	for (i = 0; i < 64; i++) {
	    switch ((env->itlb_tte[i] >> 61) & 3) {
	    default:
	    case 0x0:
		mask = "  8k";
		break;
	    case 0x1:
		mask = " 64k";
		break;
	    case 0x2:
		mask = "512k";
		break;
	    case 0x3:
		mask = "  4M";
		break;
	    }
	    if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
		printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, ctx %lld\n",
		       env->itlb_tag[i] & ~0x1fffULL,
		       env->itlb_tte[i] & 0x1ffffffe000ULL,
		       mask,
		       env->itlb_tte[i] & 0x4? "priv": "user",
		       env->itlb_tte[i] & 0x40? "locked": "unlocked",
		       env->itlb_tag[i] & 0x1fffULL);
	    }
	}
    }
}
#endif
bellard's avatar
bellard committed
572
#endif