Revision 83469015 target-sparc/helper.c

b/target-sparc/helper.c
1 1
/*
2 2
 *  sparc helpers
3 3
 * 
4
 *  Copyright (c) 2003 Fabrice Bellard
4
 *  Copyright (c) 2003-2005 Fabrice Bellard
5 5
 *
6 6
 * This library is free software; you can redistribute it and/or
7 7
 * modify it under the terms of the GNU Lesser General Public
......
28 28
#include "cpu.h"
29 29
#include "exec-all.h"
30 30

  
31
//#define DEBUG_PCALL
32 31
//#define DEBUG_MMU
33 32

  
34 33
/* Sparc MMU emulation */
......
62 61
#else
63 62

  
64 63
#ifndef TARGET_SPARC64
64
/*
65
 * Sparc V8 Reference MMU (SRMMU)
66
 */
65 67
static const int access_table[8][8] = {
66 68
    { 0, 0, 0, 0, 2, 0, 3, 3 },
67 69
    { 0, 0, 0, 0, 2, 0, 0, 0 },
......
229 231
    }
230 232
}
231 233
#else
234
/*
235
 * UltraSparc IIi I/DMMUs
236
 */
232 237
static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot,
233 238
			  int *access_index, target_ulong address, int rw,
234 239
			  int is_user)
......
237 242
    unsigned int i;
238 243

  
239 244
    if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
240
	*physical = address & 0xffffffff;
245
	*physical = address;
241 246
	*prot = PAGE_READ | PAGE_WRITE;
242 247
        return 0;
243 248
    }
244 249

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

  
......
288 302
    unsigned int i;
289 303

  
290 304
    if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
291
	*physical = address & 0xffffffff;
305
	*physical = address;
292 306
	*prot = PAGE_READ;
293 307
        return 0;
294 308
    }
309

  
295 310
    for (i = 0; i < 64; i++) {
296
	if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
297
	    switch (env->itlb_tte[i] >> 60) {
298
	    default:
299
	    case 0x4: // 8k
300
		mask = 0xffffffffffffe000ULL;
301
		break;
302
	    case 0x5: // 64k
303
		mask = 0xffffffffffff0000ULL;
304
		break;
305
	    case 0x6: // 512k
306
		mask = 0xfffffffffff80000ULL;
307
		break;
308
	    case 0x7: // 4M
309
		mask = 0xffffffffffc00000ULL;
311
	switch ((env->itlb_tte[i] >> 61) & 3) {
312
	default:
313
	case 0x0: // 8k
314
	    mask = 0xffffffffffffe000ULL;
315
	    break;
316
	case 0x1: // 64k
317
	    mask = 0xffffffffffff0000ULL;
318
	    break;
319
	case 0x2: // 512k
320
	    mask = 0xfffffffffff80000ULL;
321
	    break;
322
	case 0x3: // 4M
323
	    mask = 0xffffffffffc00000ULL;
310 324
		break;
325
	}
326
	// ctx match, vaddr match?
327
	if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
328
	    (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
329
	    // valid, access ok?
330
	    if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
331
		((env->itlb_tte[i] & 0x4) && is_user)) {
332
		if (env->immuregs[3]) /* Fault status register */
333
		    env->immuregs[3] = 2; /* overflow (not read before another fault) */
334
		env->immuregs[3] |= (is_user << 3) | 1;
335
		env->exception_index = TT_TFAULT;
336
#ifdef DEBUG_MMU
337
		printf("TFAULT at 0x%llx\n", address);
338
#endif
339
		return 1;
311 340
	    }
312
	    // ctx match, vaddr match?
313
	    if (env->immuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
314
		(address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
315
		// access ok?
316
		if ((env->itlb_tte[i] & 0x4) && !(env->pstate & PS_PRIV)) {
317
		    env->exception_index = TT_TFAULT;
318
		    return 1;
319
		}
320
		*physical = env->itlb_tte[i] & 0xffffe000;
321
		*prot = PAGE_READ;
322
		return 0;
323
	    }
341
	    *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
342
	    *prot = PAGE_READ;
343
	    return 0;
324 344
	}
325 345
    }
326
    env->exception_index = TT_TFAULT;
346
#ifdef DEBUG_MMU
347
    printf("TMISS at 0x%llx\n", address);
348
#endif
349
    env->exception_index = TT_TMISS;
327 350
    return 1;
328 351
}
329 352

  
......
341 364
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
342 365
                              int is_user, int is_softmmu)
343 366
{
344
    target_ulong virt_addr;
367
    target_ulong virt_addr, vaddr;
345 368
    target_phys_addr_t paddr;
346
    unsigned long vaddr;
347 369
    int error_code = 0, prot, ret = 0, access_index;
348 370

  
349 371
    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
350 372
    if (error_code == 0) {
351 373
	virt_addr = address & TARGET_PAGE_MASK;
352 374
	vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
375
#ifdef DEBUG_MMU
376
	printf("Translate at 0x%llx -> 0x%llx, vaddr 0x%llx\n", address, paddr, vaddr);
377
#endif
353 378
	ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
354 379
	return ret;
355 380
    }
......
471 496
    printf("MMU dump ends\n");
472 497
}
473 498
#endif
499
#else
500
#ifdef DEBUG_MMU
501
void dump_mmu(CPUState *env)
502
{
503
    unsigned int i;
504
    const char *mask;
505

  
506
    printf("MMU contexts: Primary: %lld, Secondary: %lld\n", env->dmmuregs[1], env->dmmuregs[2]);
507
    if ((env->lsu & DMMU_E) == 0) {
508
	printf("DMMU disabled\n");
509
    } else {
510
	printf("DMMU dump:\n");
511
	for (i = 0; i < 64; i++) {
512
	    switch ((env->dtlb_tte[i] >> 61) & 3) {
513
	    default:
514
	    case 0x0:
515
		mask = "  8k";
516
		break;
517
	    case 0x1:
518
		mask = " 64k";
519
		break;
520
	    case 0x2:
521
		mask = "512k";
522
		break;
523
	    case 0x3:
524
		mask = "  4M";
525
		break;
526
	    }
527
	    if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
528
		printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, %s, ctx %lld\n",
529
		       env->dtlb_tag[i] & ~0x1fffULL,
530
		       env->dtlb_tte[i] & 0x1ffffffe000ULL,
531
		       mask,
532
		       env->dtlb_tte[i] & 0x4? "priv": "user",
533
		       env->dtlb_tte[i] & 0x2? "RW": "RO",
534
		       env->dtlb_tte[i] & 0x40? "locked": "unlocked",
535
		       env->dtlb_tag[i] & 0x1fffULL);
536
	    }
537
	}
538
    }
539
    if ((env->lsu & IMMU_E) == 0) {
540
	printf("IMMU disabled\n");
541
    } else {
542
	printf("IMMU dump:\n");
543
	for (i = 0; i < 64; i++) {
544
	    switch ((env->itlb_tte[i] >> 61) & 3) {
545
	    default:
546
	    case 0x0:
547
		mask = "  8k";
548
		break;
549
	    case 0x1:
550
		mask = " 64k";
551
		break;
552
	    case 0x2:
553
		mask = "512k";
554
		break;
555
	    case 0x3:
556
		mask = "  4M";
557
		break;
558
	    }
559
	    if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
560
		printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, ctx %lld\n",
561
		       env->itlb_tag[i] & ~0x1fffULL,
562
		       env->itlb_tte[i] & 0x1ffffffe000ULL,
563
		       mask,
564
		       env->itlb_tte[i] & 0x4? "priv": "user",
565
		       env->itlb_tte[i] & 0x40? "locked": "unlocked",
566
		       env->itlb_tag[i] & 0x1fffULL);
567
	    }
568
	}
569
    }
570
}
571
#endif
474 572
#endif

Also available in: Unified diff