Commit 6e8e7d4c092951f417297120e3d3cc28840a045b

Authored by Igor Kovalenko
Committed by Blue Swirl
1 parent 33b544ba

sparc64 name mmu registers and general cleanup

- add names to mmu registers, this helps understanding the code which
uses/modifies them.
- fold i/d mmu tlb entries tag and tte arrays into arrays of tlb entries
- extract demap_tlb routine (code duplication)
- extract replace_tlb routine (code duplication)

- flush qemu tlb translations when replacing sparc64 mmu tlb entries

I have no test case which demands flushing qemu translations,
and this patch should have no other visible changes to runtime.

Signed-off-by: igor.v.kovalenko@gmail.com

--
Kind regards,
Igor V. Kovalenko
target-sparc/cpu.h
@@ -273,6 +273,11 @@ enum { @@ -273,6 +273,11 @@ enum {
273 }; 273 };
274 #endif 274 #endif
275 275
  276 +typedef struct SparcTLBEntry {
  277 + uint64_t tag;
  278 + uint64_t tte;
  279 +} SparcTLBEntry;
  280 +
276 typedef struct CPUSPARCState { 281 typedef struct CPUSPARCState {
277 target_ulong gregs[8]; /* general registers */ 282 target_ulong gregs[8]; /* general registers */
278 target_ulong *regwptr; /* pointer to current register window */ 283 target_ulong *regwptr; /* pointer to current register window */
@@ -319,12 +324,33 @@ typedef struct CPUSPARCState { @@ -319,12 +324,33 @@ typedef struct CPUSPARCState {
319 uint64_t lsu; 324 uint64_t lsu;
320 #define DMMU_E 0x8 325 #define DMMU_E 0x8
321 #define IMMU_E 0x4 326 #define IMMU_E 0x4
322 - uint64_t immuregs[16];  
323 - uint64_t dmmuregs[16];  
324 - uint64_t itlb_tag[64];  
325 - uint64_t itlb_tte[64];  
326 - uint64_t dtlb_tag[64];  
327 - uint64_t dtlb_tte[64]; 327 + //typedef struct SparcMMU
  328 + union {
  329 + uint64_t immuregs[16];
  330 + struct {
  331 + uint64_t tsb_tag_target;
  332 + uint64_t unused_mmu_primary_context; // use DMMU
  333 + uint64_t unused_mmu_secondary_context; // use DMMU
  334 + uint64_t sfsr;
  335 + uint64_t sfar;
  336 + uint64_t tsb;
  337 + uint64_t tag_access;
  338 + } immu;
  339 + };
  340 + union {
  341 + uint64_t dmmuregs[16];
  342 + struct {
  343 + uint64_t tsb_tag_target;
  344 + uint64_t mmu_primary_context;
  345 + uint64_t mmu_secondary_context;
  346 + uint64_t sfsr;
  347 + uint64_t sfar;
  348 + uint64_t tsb;
  349 + uint64_t tag_access;
  350 + } dmmu;
  351 + };
  352 + SparcTLBEntry itlb[64];
  353 + SparcTLBEntry dtlb[64];
328 uint32_t mmu_version; 354 uint32_t mmu_version;
329 #else 355 #else
330 uint32_t mmuregs[32]; 356 uint32_t mmuregs[32];
target-sparc/helper.c
@@ -386,13 +386,13 @@ static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask) @@ -386,13 +386,13 @@ static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
386 386
387 // Returns true if TTE tag is valid and matches virtual address value in context 387 // Returns true if TTE tag is valid and matches virtual address value in context
388 // requires virtual address mask value calculated from TTE entry size 388 // requires virtual address mask value calculated from TTE entry size
389 -static inline int ultrasparc_tag_match(uint64_t tlb_tag, uint64_t tlb_tte, 389 +static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
390 uint64_t address, uint64_t context, 390 uint64_t address, uint64_t context,
391 target_phys_addr_t *physical) 391 target_phys_addr_t *physical)
392 { 392 {
393 uint64_t mask; 393 uint64_t mask;
394 394
395 - switch ((tlb_tte >> 61) & 3) { 395 + switch ((tlb->tte >> 61) & 3) {
396 default: 396 default:
397 case 0x0: // 8k 397 case 0x0: // 8k
398 mask = 0xffffffffffffe000ULL; 398 mask = 0xffffffffffffe000ULL;
@@ -409,12 +409,12 @@ static inline int ultrasparc_tag_match(uint64_t tlb_tag, uint64_t tlb_tte, @@ -409,12 +409,12 @@ static inline int ultrasparc_tag_match(uint64_t tlb_tag, uint64_t tlb_tte,
409 } 409 }
410 410
411 // valid, context match, virtual address match? 411 // valid, context match, virtual address match?
412 - if ((tlb_tte & 0x8000000000000000ULL) &&  
413 - compare_masked(context, tlb_tag, 0x1fff) &&  
414 - compare_masked(address, tlb_tag, mask)) 412 + if ((tlb->tte & 0x8000000000000000ULL) &&
  413 + compare_masked(context, tlb->tag, 0x1fff) &&
  414 + compare_masked(address, tlb->tag, mask))
415 { 415 {
416 // decode physical address 416 // decode physical address
417 - *physical = ((tlb_tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL; 417 + *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
418 return 1; 418 return 1;
419 } 419 }
420 420
@@ -434,21 +434,31 @@ static int get_physical_address_data(CPUState *env, @@ -434,21 +434,31 @@ static int get_physical_address_data(CPUState *env,
434 return 0; 434 return 0;
435 } 435 }
436 436
437 - context = env->dmmuregs[1] & 0x1fff; 437 + context = env->dmmu.mmu_primary_context & 0x1fff;
438 438
439 for (i = 0; i < 64; i++) { 439 for (i = 0; i < 64; i++) {
440 // ctx match, vaddr match, valid? 440 // ctx match, vaddr match, valid?
441 - if (ultrasparc_tag_match(env->dtlb_tag[i], env->dtlb_tte[i], 441 + if (ultrasparc_tag_match(&env->dtlb[i],
442 address, context, physical) 442 address, context, physical)
443 ) { 443 ) {
444 // access ok? 444 // access ok?
445 - if (((env->dtlb_tte[i] & 0x4) && is_user) ||  
446 - (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {  
447 - if (env->dmmuregs[3]) /* Fault status register */  
448 - env->dmmuregs[3] = 2; /* overflow (not read before 445 + if (((env->dtlb[i].tte & 0x4) && is_user) ||
  446 + (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
  447 + uint8_t fault_type = 0;
  448 +
  449 + if ((env->dtlb[i].tte & 0x4) && is_user) {
  450 + fault_type |= 1; /* privilege violation */
  451 + }
  452 +
  453 + if (env->dmmu.sfsr & 1) /* Fault status register */
  454 + env->dmmu.sfsr = 2; /* overflow (not read before
449 another fault) */ 455 another fault) */
450 - env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;  
451 - env->dmmuregs[4] = address; /* Fault address register */ 456 +
  457 + env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
  458 +
  459 + env->dmmu.sfsr |= (fault_type << 7);
  460 +
  461 + env->dmmu.sfar = address; /* Fault address register */
452 env->exception_index = TT_DFAULT; 462 env->exception_index = TT_DFAULT;
453 #ifdef DEBUG_MMU 463 #ifdef DEBUG_MMU
454 printf("DFAULT at 0x%" PRIx64 "\n", address); 464 printf("DFAULT at 0x%" PRIx64 "\n", address);
@@ -456,7 +466,7 @@ static int get_physical_address_data(CPUState *env, @@ -456,7 +466,7 @@ static int get_physical_address_data(CPUState *env,
456 return 1; 466 return 1;
457 } 467 }
458 *prot = PAGE_READ; 468 *prot = PAGE_READ;
459 - if (env->dtlb_tte[i] & 0x2) 469 + if (env->dtlb[i].tte & 0x2)
460 *prot |= PAGE_WRITE; 470 *prot |= PAGE_WRITE;
461 return 0; 471 return 0;
462 } 472 }
@@ -464,7 +474,7 @@ static int get_physical_address_data(CPUState *env, @@ -464,7 +474,7 @@ static int get_physical_address_data(CPUState *env,
464 #ifdef DEBUG_MMU 474 #ifdef DEBUG_MMU
465 printf("DMISS at 0x%" PRIx64 "\n", address); 475 printf("DMISS at 0x%" PRIx64 "\n", address);
466 #endif 476 #endif
467 - env->dmmuregs[6] = (address & ~0x1fffULL) | context; 477 + env->dmmu.tag_access = (address & ~0x1fffULL) | context;
468 env->exception_index = TT_DMISS; 478 env->exception_index = TT_DMISS;
469 return 1; 479 return 1;
470 } 480 }
@@ -483,19 +493,19 @@ static int get_physical_address_code(CPUState *env, @@ -483,19 +493,19 @@ static int get_physical_address_code(CPUState *env,
483 return 0; 493 return 0;
484 } 494 }
485 495
486 - context = env->dmmuregs[1] & 0x1fff; 496 + context = env->dmmu.mmu_primary_context & 0x1fff;
487 497
488 for (i = 0; i < 64; i++) { 498 for (i = 0; i < 64; i++) {
489 // ctx match, vaddr match, valid? 499 // ctx match, vaddr match, valid?
490 - if (ultrasparc_tag_match(env->itlb_tag[i], env->itlb_tte[i], 500 + if (ultrasparc_tag_match(&env->itlb[i],
491 address, context, physical) 501 address, context, physical)
492 ) { 502 ) {
493 // access ok? 503 // access ok?
494 - if ((env->itlb_tte[i] & 0x4) && is_user) {  
495 - if (env->immuregs[3]) /* Fault status register */  
496 - env->immuregs[3] = 2; /* overflow (not read before 504 + if ((env->itlb[i].tte & 0x4) && is_user) {
  505 + if (env->immu.sfsr) /* Fault status register */
  506 + env->immu.sfsr = 2; /* overflow (not read before
497 another fault) */ 507 another fault) */
498 - env->immuregs[3] |= (is_user << 3) | 1; 508 + env->immu.sfsr |= (is_user << 3) | 1;
499 env->exception_index = TT_TFAULT; 509 env->exception_index = TT_TFAULT;
500 #ifdef DEBUG_MMU 510 #ifdef DEBUG_MMU
501 printf("TFAULT at 0x%" PRIx64 "\n", address); 511 printf("TFAULT at 0x%" PRIx64 "\n", address);
@@ -510,7 +520,7 @@ static int get_physical_address_code(CPUState *env, @@ -510,7 +520,7 @@ static int get_physical_address_code(CPUState *env,
510 printf("TMISS at 0x%" PRIx64 "\n", address); 520 printf("TMISS at 0x%" PRIx64 "\n", address);
511 #endif 521 #endif
512 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */ 522 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
513 - env->immuregs[6] = (address & ~0x1fffULL) | context; 523 + env->immu.tag_access = (address & ~0x1fffULL) | context;
514 env->exception_index = TT_TMISS; 524 env->exception_index = TT_TMISS;
515 return 1; 525 return 1;
516 } 526 }
@@ -561,7 +571,7 @@ void dump_mmu(CPUState *env) @@ -561,7 +571,7 @@ void dump_mmu(CPUState *env)
561 const char *mask; 571 const char *mask;
562 572
563 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n", 573 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
564 - env->dmmuregs[1], env->dmmuregs[2]); 574 + env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
565 if ((env->lsu & DMMU_E) == 0) { 575 if ((env->lsu & DMMU_E) == 0) {
566 printf("DMMU disabled\n"); 576 printf("DMMU disabled\n");
567 } else { 577 } else {
@@ -583,8 +593,9 @@ void dump_mmu(CPUState *env) @@ -583,8 +593,9 @@ void dump_mmu(CPUState *env)
583 break; 593 break;
584 } 594 }
585 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) { 595 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
586 - printf("VA: %" PRIx64 ", PA: %" PRIx64 596 + printf("[%02u] VA: " PRIx64 ", PA: " PRIx64
587 ", %s, %s, %s, %s, ctx %" PRId64 "\n", 597 ", %s, %s, %s, %s, ctx %" PRId64 "\n",
  598 + i,
588 env->dtlb_tag[i] & (uint64_t)~0x1fffULL, 599 env->dtlb_tag[i] & (uint64_t)~0x1fffULL,
589 env->dtlb_tte[i] & (uint64_t)0x1ffffffe000ULL, 600 env->dtlb_tte[i] & (uint64_t)0x1ffffffe000ULL,
590 mask, 601 mask,
@@ -616,14 +627,15 @@ void dump_mmu(CPUState *env) @@ -616,14 +627,15 @@ void dump_mmu(CPUState *env)
616 break; 627 break;
617 } 628 }
618 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) { 629 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
619 - printf("VA: %" PRIx64 ", PA: %" PRIx64 630 + printf("[%02u] VA: " PRIx64 ", PA: " PRIx64
620 ", %s, %s, %s, ctx %" PRId64 "\n", 631 ", %s, %s, %s, ctx %" PRId64 "\n",
621 - env->itlb_tag[i] & (uint64_t)~0x1fffULL, 632 + i,
  633 + env->itlb[i].tag & (uint64_t)~0x1fffULL,
622 env->itlb_tte[i] & (uint64_t)0x1ffffffe000ULL, 634 env->itlb_tte[i] & (uint64_t)0x1ffffffe000ULL,
623 mask, 635 mask,
624 env->itlb_tte[i] & 0x4? "priv": "user", 636 env->itlb_tte[i] & 0x4? "priv": "user",
625 env->itlb_tte[i] & 0x40? "locked": "unlocked", 637 env->itlb_tte[i] & 0x40? "locked": "unlocked",
626 - env->itlb_tag[i] & (uint64_t)0x1fffULL); 638 + env->itlb[i].tag & (uint64_t)0x1fffULL);
627 } 639 }
628 } 640 }
629 } 641 }
target-sparc/machine.c
@@ -52,10 +52,10 @@ void cpu_save(QEMUFile *f, void *opaque) @@ -52,10 +52,10 @@ void cpu_save(QEMUFile *f, void *opaque)
52 qemu_put_be64s(f, &env->dmmuregs[i]); 52 qemu_put_be64s(f, &env->dmmuregs[i]);
53 } 53 }
54 for (i = 0; i < 64; i++) { 54 for (i = 0; i < 64; i++) {
55 - qemu_put_be64s(f, &env->itlb_tag[i]);  
56 - qemu_put_be64s(f, &env->itlb_tte[i]);  
57 - qemu_put_be64s(f, &env->dtlb_tag[i]);  
58 - qemu_put_be64s(f, &env->dtlb_tte[i]); 55 + qemu_put_be64s(f, &env->itlb[i].tag);
  56 + qemu_put_be64s(f, &env->itlb[i].tte);
  57 + qemu_put_be64s(f, &env->dtlb[i].tag);
  58 + qemu_put_be64s(f, &env->dtlb[i].tte);
59 } 59 }
60 qemu_put_be32s(f, &env->mmu_version); 60 qemu_put_be32s(f, &env->mmu_version);
61 for (i = 0; i < MAXTL_MAX; i++) { 61 for (i = 0; i < MAXTL_MAX; i++) {
@@ -148,10 +148,10 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) @@ -148,10 +148,10 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
148 qemu_get_be64s(f, &env->dmmuregs[i]); 148 qemu_get_be64s(f, &env->dmmuregs[i]);
149 } 149 }
150 for (i = 0; i < 64; i++) { 150 for (i = 0; i < 64; i++) {
151 - qemu_get_be64s(f, &env->itlb_tag[i]);  
152 - qemu_get_be64s(f, &env->itlb_tte[i]);  
153 - qemu_get_be64s(f, &env->dtlb_tag[i]);  
154 - qemu_get_be64s(f, &env->dtlb_tte[i]); 151 + qemu_get_be64s(f, &env->itlb[i].tag);
  152 + qemu_get_be64s(f, &env->itlb[i].tte);
  153 + qemu_get_be64s(f, &env->dtlb[i].tag);
  154 + qemu_get_be64s(f, &env->dtlb[i].tte);
155 } 155 }
156 qemu_get_be32s(f, &env->mmu_version); 156 qemu_get_be32s(f, &env->mmu_version);
157 for (i = 0; i < MAXTL_MAX; i++) { 157 for (i = 0; i < MAXTL_MAX; i++) {
target-sparc/op_helper.c
@@ -46,8 +46,8 @@ static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register, @@ -46,8 +46,8 @@ static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
46 int page_size) 46 int page_size)
47 { 47 {
48 uint64_t tsb_base = tsb_register & ~0x1fffULL; 48 uint64_t tsb_base = tsb_register & ~0x1fffULL;
49 - int tsb_split = (env->dmmuregs[5] & 0x1000ULL) ? 1 : 0;  
50 - int tsb_size = env->dmmuregs[5] & 0xf; 49 + int tsb_split = (tsb_register & 0x1000ULL) ? 1 : 0;
  50 + int tsb_size = tsb_register & 0xf;
51 51
52 // discard lower 13 bits which hold tag access context 52 // discard lower 13 bits which hold tag access context
53 uint64_t tag_access_va = tag_access_register & ~0x1fffULL; 53 uint64_t tag_access_va = tag_access_register & ~0x1fffULL;
@@ -87,6 +87,55 @@ static uint64_t ultrasparc_tag_target(uint64_t tag_access_register) @@ -87,6 +87,55 @@ static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
87 return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22); 87 return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22);
88 } 88 }
89 89
  90 +static void replace_tlb_entry(SparcTLBEntry *tlb, CPUState *env1,
  91 + uint64_t tlb_tag, uint64_t tlb_tte)
  92 +{
  93 + target_ulong mask, size, va, offset;
  94 +
  95 + // flush page range if translation is valid
  96 + if (tlb->tte & 0x8000000000000000ULL) {
  97 +
  98 + mask = 0xffffffffffffe000ULL;
  99 + mask <<= 3 * ((tlb->tte >> 61) & 3);
  100 + size = ~mask + 1;
  101 +
  102 + va = tlb->tag & mask;
  103 +
  104 + for (offset = 0; offset < size; offset += TARGET_PAGE_SIZE) {
  105 + tlb_flush_page(env1, va + offset);
  106 + }
  107 + }
  108 +
  109 + tlb->tag = tlb_tag;
  110 + tlb->tte = tlb_tte;
  111 +}
  112 +
  113 +static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
  114 + CPUState *env1)
  115 +{
  116 + unsigned int i;
  117 + target_ulong mask;
  118 +
  119 + for (i = 0; i < 64; i++) {
  120 + if (tlb[i].tte & 0x8000000000000000ULL) {
  121 +
  122 + mask = 0xffffffffffffe000ULL;
  123 + mask <<= 3 * ((tlb[i].tte >> 61) & 3);
  124 +
  125 + if ((demap_addr & mask) == (tlb[i].tag & mask)) {
  126 + replace_tlb_entry(&tlb[i], env1, 0, 0);
  127 +#ifdef DEBUG_MMU
  128 + DPRINTF_MMU("mmu demap invalidated entry [%02u]\n",
  129 + i);
  130 + dump_mmu(env);
  131 +#endif
  132 + }
  133 + //return;
  134 + }
  135 + }
  136 +
  137 +}
  138 +
90 #endif 139 #endif
91 140
92 static inline void address_mask(CPUState *env1, target_ulong *addr) 141 static inline void address_mask(CPUState *env1, target_ulong *addr)
@@ -2143,7 +2192,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) @@ -2143,7 +2192,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2143 2192
2144 if (reg == 0) { 2193 if (reg == 0) {
2145 // I-TSB Tag Target register 2194 // I-TSB Tag Target register
2146 - ret = ultrasparc_tag_target(env->immuregs[6]); 2195 + ret = ultrasparc_tag_target(env->immu.tag_access);
2147 } else { 2196 } else {
2148 ret = env->immuregs[reg]; 2197 ret = env->immuregs[reg];
2149 } 2198 }
@@ -2154,7 +2203,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) @@ -2154,7 +2203,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2154 { 2203 {
2155 // env->immuregs[5] holds I-MMU TSB register value 2204 // env->immuregs[5] holds I-MMU TSB register value
2156 // env->immuregs[6] holds I-MMU Tag Access register value 2205 // env->immuregs[6] holds I-MMU Tag Access register value
2157 - ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6], 2206 + ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2158 8*1024); 2207 8*1024);
2159 break; 2208 break;
2160 } 2209 }
@@ -2162,7 +2211,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) @@ -2162,7 +2211,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2162 { 2211 {
2163 // env->immuregs[5] holds I-MMU TSB register value 2212 // env->immuregs[5] holds I-MMU TSB register value
2164 // env->immuregs[6] holds I-MMU Tag Access register value 2213 // env->immuregs[6] holds I-MMU Tag Access register value
2165 - ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6], 2214 + ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2166 64*1024); 2215 64*1024);
2167 break; 2216 break;
2168 } 2217 }
@@ -2170,14 +2219,14 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) @@ -2170,14 +2219,14 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2170 { 2219 {
2171 int reg = (addr >> 3) & 0x3f; 2220 int reg = (addr >> 3) & 0x3f;
2172 2221
2173 - ret = env->itlb_tte[reg]; 2222 + ret = env->itlb[reg].tte;
2174 break; 2223 break;
2175 } 2224 }
2176 case 0x56: // I-MMU tag read 2225 case 0x56: // I-MMU tag read
2177 { 2226 {
2178 int reg = (addr >> 3) & 0x3f; 2227 int reg = (addr >> 3) & 0x3f;
2179 2228
2180 - ret = env->itlb_tag[reg]; 2229 + ret = env->itlb[reg].tag;
2181 break; 2230 break;
2182 } 2231 }
2183 case 0x58: // D-MMU regs 2232 case 0x58: // D-MMU regs
@@ -2186,7 +2235,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) @@ -2186,7 +2235,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2186 2235
2187 if (reg == 0) { 2236 if (reg == 0) {
2188 // D-TSB Tag Target register 2237 // D-TSB Tag Target register
2189 - ret = ultrasparc_tag_target(env->dmmuregs[6]); 2238 + ret = ultrasparc_tag_target(env->dmmu.tag_access);
2190 } else { 2239 } else {
2191 ret = env->dmmuregs[reg]; 2240 ret = env->dmmuregs[reg];
2192 } 2241 }
@@ -2196,7 +2245,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) @@ -2196,7 +2245,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2196 { 2245 {
2197 // env->dmmuregs[5] holds D-MMU TSB register value 2246 // env->dmmuregs[5] holds D-MMU TSB register value
2198 // env->dmmuregs[6] holds D-MMU Tag Access register value 2247 // env->dmmuregs[6] holds D-MMU Tag Access register value
2199 - ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6], 2248 + ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2200 8*1024); 2249 8*1024);
2201 break; 2250 break;
2202 } 2251 }
@@ -2204,7 +2253,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) @@ -2204,7 +2253,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2204 { 2253 {
2205 // env->dmmuregs[5] holds D-MMU TSB register value 2254 // env->dmmuregs[5] holds D-MMU TSB register value
2206 // env->dmmuregs[6] holds D-MMU Tag Access register value 2255 // env->dmmuregs[6] holds D-MMU Tag Access register value
2207 - ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6], 2256 + ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2208 64*1024); 2257 64*1024);
2209 break; 2258 break;
2210 } 2259 }
@@ -2212,14 +2261,14 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) @@ -2212,14 +2261,14 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2212 { 2261 {
2213 int reg = (addr >> 3) & 0x3f; 2262 int reg = (addr >> 3) & 0x3f;
2214 2263
2215 - ret = env->dtlb_tte[reg]; 2264 + ret = env->dtlb[reg].tte;
2216 break; 2265 break;
2217 } 2266 }
2218 case 0x5e: // D-MMU tag read 2267 case 0x5e: // D-MMU tag read
2219 { 2268 {
2220 int reg = (addr >> 3) & 0x3f; 2269 int reg = (addr >> 3) & 0x3f;
2221 2270
2222 - ret = env->dtlb_tag[reg]; 2271 + ret = env->dtlb[reg].tag;
2223 break; 2272 break;
2224 } 2273 }
2225 case 0x46: // D-cache data 2274 case 0x46: // D-cache data
@@ -2462,25 +2511,34 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) @@ -2462,25 +2511,34 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2462 oldreg = env->immuregs[reg]; 2511 oldreg = env->immuregs[reg];
2463 switch(reg) { 2512 switch(reg) {
2464 case 0: // RO 2513 case 0: // RO
2465 - case 4:  
2466 return; 2514 return;
2467 case 1: // Not in I-MMU 2515 case 1: // Not in I-MMU
2468 case 2: 2516 case 2:
2469 - case 7:  
2470 - case 8:  
2471 return; 2517 return;
2472 case 3: // SFSR 2518 case 3: // SFSR
2473 if ((val & 1) == 0) 2519 if ((val & 1) == 0)
2474 val = 0; // Clear SFSR 2520 val = 0; // Clear SFSR
  2521 + env->immu.sfsr = val;
2475 break; 2522 break;
  2523 + case 4: // RO
  2524 + return;
2476 case 5: // TSB access 2525 case 5: // TSB access
  2526 + DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016"
  2527 + PRIx64 "\n", env->immu.tsb, val);
  2528 + env->immu.tsb = val;
  2529 + break;
2477 case 6: // Tag access 2530 case 6: // Tag access
  2531 + env->immu.tag_access = val;
  2532 + break;
  2533 + case 7:
  2534 + case 8:
  2535 + return;
2478 default: 2536 default:
2479 break; 2537 break;
2480 } 2538 }
2481 - env->immuregs[reg] = val; 2539 +
2482 if (oldreg != env->immuregs[reg]) { 2540 if (oldreg != env->immuregs[reg]) {
2483 - DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" 2541 + DPRINTF_MMU("immu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
2484 PRIx64 "\n", reg, oldreg, env->immuregs[reg]); 2542 PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
2485 } 2543 }
2486 #ifdef DEBUG_MMU 2544 #ifdef DEBUG_MMU
@@ -2494,20 +2552,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) @@ -2494,20 +2552,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2494 2552
2495 // Try finding an invalid entry 2553 // Try finding an invalid entry
2496 for (i = 0; i < 64; i++) { 2554 for (i = 0; i < 64; i++) {
2497 - if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {  
2498 - env->itlb_tag[i] = env->immuregs[6];  
2499 - env->itlb_tte[i] = val; 2555 + if ((env->itlb[i].tte & 0x8000000000000000ULL) == 0) {
  2556 + replace_tlb_entry(&env->itlb[i], env,
  2557 + env->immu.tag_access, val);
  2558 +#ifdef DEBUG_MMU
  2559 + DPRINTF_MMU("immu data map replaced invalid entry [%i]\n",
  2560 + i);
  2561 + dump_mmu(env);
  2562 +#endif
2500 return; 2563 return;
2501 } 2564 }
2502 } 2565 }
2503 // Try finding an unlocked entry 2566 // Try finding an unlocked entry
2504 for (i = 0; i < 64; i++) { 2567 for (i = 0; i < 64; i++) {
2505 - if ((env->itlb_tte[i] & 0x40) == 0) {  
2506 - env->itlb_tag[i] = env->immuregs[6];  
2507 - env->itlb_tte[i] = val; 2568 + if ((env->itlb[i].tte & 0x40) == 0) {
  2569 + replace_tlb_entry(&env->itlb[i], env,
  2570 + env->immu.tag_access, val);
  2571 +#ifdef DEBUG_MMU
  2572 + DPRINTF_MMU("immu data map replaced unlocked entry [%i]\n",
  2573 + i);
  2574 + dump_mmu(env);
  2575 +#endif
2508 return; 2576 return;
2509 } 2577 }
2510 } 2578 }
  2579 +#ifdef DEBUG_MMU
  2580 + DPRINTF_MMU("immu data map failed: no entries available\n");
  2581 +#endif
2511 // error state? 2582 // error state?
2512 return; 2583 return;
2513 } 2584 }
@@ -2517,27 +2588,18 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) @@ -2517,27 +2588,18 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2517 2588
2518 unsigned int i = (addr >> 3) & 0x3f; 2589 unsigned int i = (addr >> 3) & 0x3f;
2519 2590
2520 - env->itlb_tag[i] = env->immuregs[6];  
2521 - env->itlb_tte[i] = val; 2591 + replace_tlb_entry(&env->itlb[i], env,
  2592 + env->immu.tag_access, val);
  2593 +
  2594 +#ifdef DEBUG_MMU
  2595 + DPRINTF_MMU("immu data access replaced entry [%i]\n",
  2596 + i);
  2597 + dump_mmu(env);
  2598 +#endif
2522 return; 2599 return;
2523 } 2600 }
2524 case 0x57: // I-MMU demap 2601 case 0x57: // I-MMU demap
2525 - {  
2526 - unsigned int i;  
2527 -  
2528 - for (i = 0; i < 64; i++) {  
2529 - if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {  
2530 - target_ulong mask = 0xffffffffffffe000ULL;  
2531 -  
2532 - mask <<= 3 * ((env->itlb_tte[i] >> 61) & 3);  
2533 - if ((val & mask) == (env->itlb_tag[i] & mask)) {  
2534 - env->itlb_tag[i] = 0;  
2535 - env->itlb_tte[i] = 0;  
2536 - }  
2537 - return;  
2538 - }  
2539 - }  
2540 - } 2602 + demap_tlb(env->itlb, val, env);
2541 return; 2603 return;
2542 case 0x58: // D-MMU regs 2604 case 0x58: // D-MMU regs
2543 { 2605 {
@@ -2552,22 +2614,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) @@ -2552,22 +2614,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2552 case 3: // SFSR 2614 case 3: // SFSR
2553 if ((val & 1) == 0) { 2615 if ((val & 1) == 0) {
2554 val = 0; // Clear SFSR, Fault address 2616 val = 0; // Clear SFSR, Fault address
2555 - env->dmmuregs[4] = 0; 2617 + env->dmmu.sfar = 0;
2556 } 2618 }
2557 - env->dmmuregs[reg] = val; 2619 + env->dmmu.sfsr = val;
2558 break; 2620 break;
2559 case 1: // Primary context 2621 case 1: // Primary context
  2622 + env->dmmu.mmu_primary_context = val;
  2623 + break;
2560 case 2: // Secondary context 2624 case 2: // Secondary context
  2625 + env->dmmu.mmu_secondary_context = val;
  2626 + break;
2561 case 5: // TSB access 2627 case 5: // TSB access
  2628 + DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
  2629 + PRIx64 "\n", env->dmmu.tsb, val);
  2630 + env->dmmu.tsb = val;
  2631 + break;
2562 case 6: // Tag access 2632 case 6: // Tag access
  2633 + env->dmmu.tag_access = val;
  2634 + break;
2563 case 7: // Virtual Watchpoint 2635 case 7: // Virtual Watchpoint
2564 case 8: // Physical Watchpoint 2636 case 8: // Physical Watchpoint
2565 default: 2637 default:
  2638 + env->dmmuregs[reg] = val;
2566 break; 2639 break;
2567 } 2640 }
2568 - env->dmmuregs[reg] = val; 2641 +
2569 if (oldreg != env->dmmuregs[reg]) { 2642 if (oldreg != env->dmmuregs[reg]) {
2570 - DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" 2643 + DPRINTF_MMU("dmmu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
2571 PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]); 2644 PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
2572 } 2645 }
2573 #ifdef DEBUG_MMU 2646 #ifdef DEBUG_MMU
@@ -2581,20 +2654,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) @@ -2581,20 +2654,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2581 2654
2582 // Try finding an invalid entry 2655 // Try finding an invalid entry
2583 for (i = 0; i < 64; i++) { 2656 for (i = 0; i < 64; i++) {
2584 - if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {  
2585 - env->dtlb_tag[i] = env->dmmuregs[6];  
2586 - env->dtlb_tte[i] = val; 2657 + if ((env->dtlb[i].tte & 0x8000000000000000ULL) == 0) {
  2658 + replace_tlb_entry(&env->dtlb[i], env,
  2659 + env->dmmu.tag_access, val);
  2660 +#ifdef DEBUG_MMU
  2661 + DPRINTF_MMU("dmmu data map replaced invalid entry [%i]\n",
  2662 + i);
  2663 + dump_mmu(env);
  2664 +#endif
2587 return; 2665 return;
2588 } 2666 }
2589 } 2667 }
2590 // Try finding an unlocked entry 2668 // Try finding an unlocked entry
2591 for (i = 0; i < 64; i++) { 2669 for (i = 0; i < 64; i++) {
2592 - if ((env->dtlb_tte[i] & 0x40) == 0) {  
2593 - env->dtlb_tag[i] = env->dmmuregs[6];  
2594 - env->dtlb_tte[i] = val; 2670 + if ((env->dtlb[i].tte & 0x40) == 0) {
  2671 + replace_tlb_entry(&env->dtlb[i], env,
  2672 + env->dmmu.tag_access, val);
  2673 +#ifdef DEBUG_MMU
  2674 + DPRINTF_MMU("dmmu data map replaced unlocked entry [%i]\n",
  2675 + i);
  2676 + dump_mmu(env);
  2677 +#endif
2595 return; 2678 return;
2596 } 2679 }
2597 } 2680 }
  2681 +#ifdef DEBUG_MMU
  2682 + DPRINTF_MMU("dmmu data map failed: no entries available\n");
  2683 +#endif
2598 // error state? 2684 // error state?
2599 return; 2685 return;
2600 } 2686 }
@@ -2602,27 +2688,17 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) @@ -2602,27 +2688,17 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2602 { 2688 {
2603 unsigned int i = (addr >> 3) & 0x3f; 2689 unsigned int i = (addr >> 3) & 0x3f;
2604 2690
2605 - env->dtlb_tag[i] = env->dmmuregs[6];  
2606 - env->dtlb_tte[i] = val; 2691 + replace_tlb_entry(&env->dtlb[i], env,
  2692 + env->dmmu.tag_access, val);
  2693 +#ifdef DEBUG_MMU
  2694 + DPRINTF_MMU("dmmu data access replaced entry [%i]\n",
  2695 + i);
  2696 + dump_mmu(env);
  2697 +#endif
2607 return; 2698 return;
2608 } 2699 }
2609 case 0x5f: // D-MMU demap 2700 case 0x5f: // D-MMU demap
2610 - {  
2611 - unsigned int i;  
2612 -  
2613 - for (i = 0; i < 64; i++) {  
2614 - if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {  
2615 - target_ulong mask = 0xffffffffffffe000ULL;  
2616 -  
2617 - mask <<= 3 * ((env->dtlb_tte[i] >> 61) & 3);  
2618 - if ((val & mask) == (env->dtlb_tag[i] & mask)) {  
2619 - env->dtlb_tag[i] = 0;  
2620 - env->dtlb_tte[i] = 0;  
2621 - }  
2622 - return;  
2623 - }  
2624 - }  
2625 - } 2701 + demap_tlb(env->dtlb, val, env);
2626 return; 2702 return;
2627 case 0x49: // Interrupt data receive 2703 case 0x49: // Interrupt data receive
2628 // XXX 2704 // XXX