Commit f707726e8d8308d58edbcd4664e252a445cc9b8c

Authored by Igor Kovalenko
Committed by Blue Swirl
1 parent 6e8e7d4c

sparc64 really implement itlb/dtlb automatic replacement writes

- implement "used" bit in tlb translation entry
- mark tlb entry used if qemu code/data translation succeeds
- fold i/d mmu replacement writes code into replace_tlb_1bit_lru which
adds 1bit lru replacement algorithm; previously code tried to replace
first unlocked entry only

- extract more bitmasks to named macros
- add "immu" or "dmmu" type name to debugging output where appropriate

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

--
Kind regards,
Igor V. Kovalenko
target-sparc/cpu.h
@@ -273,6 +273,17 @@ enum { @@ -273,6 +273,17 @@ enum {
273 }; 273 };
274 #endif 274 #endif
275 275
  276 +#define TTE_VALID_BIT (1ULL << 63)
  277 +#define TTE_USED_BIT (1ULL << 41)
  278 +#define TTE_LOCKED_BIT (1ULL << 6)
  279 +
  280 +#define TTE_IS_VALID(tte) ((tte) & TTE_VALID_BIT)
  281 +#define TTE_IS_USED(tte) ((tte) & TTE_USED_BIT)
  282 +#define TTE_IS_LOCKED(tte) ((tte) & TTE_LOCKED_BIT)
  283 +
  284 +#define TTE_SET_USED(tte) ((tte) |= TTE_USED_BIT)
  285 +#define TTE_SET_UNUSED(tte) ((tte) &= ~TTE_USED_BIT)
  286 +
276 typedef struct SparcTLBEntry { 287 typedef struct SparcTLBEntry {
277 uint64_t tag; 288 uint64_t tag;
278 uint64_t tte; 289 uint64_t tte;
target-sparc/helper.c
@@ -409,7 +409,7 @@ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb, @@ -409,7 +409,7 @@ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
409 } 409 }
410 410
411 // valid, context match, virtual address match? 411 // valid, context match, virtual address match?
412 - if ((tlb->tte & 0x8000000000000000ULL) && 412 + if (TTE_IS_VALID(tlb->tte) &&
413 compare_masked(context, tlb->tag, 0x1fff) && 413 compare_masked(context, tlb->tag, 0x1fff) &&
414 compare_masked(address, tlb->tag, mask)) 414 compare_masked(address, tlb->tag, mask))
415 { 415 {
@@ -468,6 +468,7 @@ static int get_physical_address_data(CPUState *env, @@ -468,6 +468,7 @@ static int get_physical_address_data(CPUState *env,
468 *prot = PAGE_READ; 468 *prot = PAGE_READ;
469 if (env->dtlb[i].tte & 0x2) 469 if (env->dtlb[i].tte & 0x2)
470 *prot |= PAGE_WRITE; 470 *prot |= PAGE_WRITE;
  471 + TTE_SET_USED(env->dtlb[i].tte);
471 return 0; 472 return 0;
472 } 473 }
473 } 474 }
@@ -513,6 +514,7 @@ static int get_physical_address_code(CPUState *env, @@ -513,6 +514,7 @@ static int get_physical_address_code(CPUState *env,
513 return 1; 514 return 1;
514 } 515 }
515 *prot = PAGE_EXEC; 516 *prot = PAGE_EXEC;
  517 + TTE_SET_USED(env->itlb[i].tte);
516 return 0; 518 return 0;
517 } 519 }
518 } 520 }
target-sparc/op_helper.c
@@ -87,13 +87,14 @@ static uint64_t ultrasparc_tag_target(uint64_t tag_access_register) @@ -87,13 +87,14 @@ 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) 90 +static void replace_tlb_entry(SparcTLBEntry *tlb,
  91 + uint64_t tlb_tag, uint64_t tlb_tte,
  92 + CPUState *env1)
92 { 93 {
93 target_ulong mask, size, va, offset; 94 target_ulong mask, size, va, offset;
94 95
95 // flush page range if translation is valid 96 // flush page range if translation is valid
96 - if (tlb->tte & 0x8000000000000000ULL) { 97 + if (TTE_IS_VALID(tlb->tte)) {
97 98
98 mask = 0xffffffffffffe000ULL; 99 mask = 0xffffffffffffe000ULL;
99 mask <<= 3 * ((tlb->tte >> 61) & 3); 100 mask <<= 3 * ((tlb->tte >> 61) & 3);
@@ -111,23 +112,22 @@ static void replace_tlb_entry(SparcTLBEntry *tlb, CPUState *env1, @@ -111,23 +112,22 @@ static void replace_tlb_entry(SparcTLBEntry *tlb, CPUState *env1,
111 } 112 }
112 113
113 static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr, 114 static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
114 - CPUState *env1) 115 + const char* strmmu, CPUState *env1)
115 { 116 {
116 unsigned int i; 117 unsigned int i;
117 target_ulong mask; 118 target_ulong mask;
118 119
119 for (i = 0; i < 64; i++) { 120 for (i = 0; i < 64; i++) {
120 - if (tlb[i].tte & 0x8000000000000000ULL) { 121 + if (TTE_IS_VALID(tlb[i].tte)) {
121 122
122 mask = 0xffffffffffffe000ULL; 123 mask = 0xffffffffffffe000ULL;
123 mask <<= 3 * ((tlb[i].tte >> 61) & 3); 124 mask <<= 3 * ((tlb[i].tte >> 61) & 3);
124 125
125 if ((demap_addr & mask) == (tlb[i].tag & mask)) { 126 if ((demap_addr & mask) == (tlb[i].tag & mask)) {
126 - replace_tlb_entry(&tlb[i], env1, 0, 0); 127 + replace_tlb_entry(&tlb[i], 0, 0, env1);
127 #ifdef DEBUG_MMU 128 #ifdef DEBUG_MMU
128 - DPRINTF_MMU("mmu demap invalidated entry [%02u]\n",  
129 - i);  
130 - dump_mmu(env); 129 + DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
  130 + dump_mmu(env1);
131 #endif 131 #endif
132 } 132 }
133 //return; 133 //return;
@@ -136,6 +136,56 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr, @@ -136,6 +136,56 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
136 136
137 } 137 }
138 138
  139 +static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
  140 + uint64_t tlb_tag, uint64_t tlb_tte,
  141 + const char* strmmu, CPUState *env1)
  142 +{
  143 + unsigned int i, replace_used;
  144 +
  145 + // Try replacing invalid entry
  146 + for (i = 0; i < 64; i++) {
  147 + if (!TTE_IS_VALID(tlb[i].tte)) {
  148 + replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
  149 +#ifdef DEBUG_MMU
  150 + DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
  151 + dump_mmu(env1);
  152 +#endif
  153 + return;
  154 + }
  155 + }
  156 +
  157 + // All entries are valid, try replacing unlocked entry
  158 +
  159 + for (replace_used = 0; replace_used < 2; ++replace_used) {
  160 +
  161 + // Used entries are not replaced on first pass
  162 +
  163 + for (i = 0; i < 64; i++) {
  164 + if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
  165 +
  166 + replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
  167 +#ifdef DEBUG_MMU
  168 + DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
  169 + strmmu, (replace_used?"used":"unused"), i);
  170 + dump_mmu(env1);
  171 +#endif
  172 + return;
  173 + }
  174 + }
  175 +
  176 + // Now reset used bit and search for unused entries again
  177 +
  178 + for (i = 0; i < 64; i++) {
  179 + TTE_SET_UNUSED(tlb[i].tte);
  180 + }
  181 + }
  182 +
  183 +#ifdef DEBUG_MMU
  184 + DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
  185 +#endif
  186 + // error state?
  187 +}
  188 +
139 #endif 189 #endif
140 190
141 static inline void address_mask(CPUState *env1, target_ulong *addr) 191 static inline void address_mask(CPUState *env1, target_ulong *addr)
@@ -2547,59 +2597,24 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) @@ -2547,59 +2597,24 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2547 return; 2597 return;
2548 } 2598 }
2549 case 0x54: // I-MMU data in 2599 case 0x54: // I-MMU data in
2550 - {  
2551 - unsigned int i;  
2552 -  
2553 - // Try finding an invalid entry  
2554 - for (i = 0; i < 64; i++) {  
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  
2563 - return;  
2564 - }  
2565 - }  
2566 - // Try finding an unlocked entry  
2567 - for (i = 0; i < 64; i++) {  
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  
2576 - return;  
2577 - }  
2578 - }  
2579 -#ifdef DEBUG_MMU  
2580 - DPRINTF_MMU("immu data map failed: no entries available\n");  
2581 -#endif  
2582 - // error state?  
2583 - return;  
2584 - } 2600 + replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
  2601 + return;
2585 case 0x55: // I-MMU data access 2602 case 0x55: // I-MMU data access
2586 { 2603 {
2587 // TODO: auto demap 2604 // TODO: auto demap
2588 2605
2589 unsigned int i = (addr >> 3) & 0x3f; 2606 unsigned int i = (addr >> 3) & 0x3f;
2590 2607
2591 - replace_tlb_entry(&env->itlb[i], env,  
2592 - env->immu.tag_access, val); 2608 + replace_tlb_entry(&env->itlb[i], env->immu.tag_access, val, env);
2593 2609
2594 #ifdef DEBUG_MMU 2610 #ifdef DEBUG_MMU
2595 - DPRINTF_MMU("immu data access replaced entry [%i]\n",  
2596 - i); 2611 + DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
2597 dump_mmu(env); 2612 dump_mmu(env);
2598 #endif 2613 #endif
2599 return; 2614 return;
2600 } 2615 }
2601 case 0x57: // I-MMU demap 2616 case 0x57: // I-MMU demap
2602 - demap_tlb(env->itlb, val, env); 2617 + demap_tlb(env->itlb, val, "immu", env);
2603 return; 2618 return;
2604 case 0x58: // D-MMU regs 2619 case 0x58: // D-MMU regs
2605 { 2620 {
@@ -2649,56 +2664,22 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) @@ -2649,56 +2664,22 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2649 return; 2664 return;
2650 } 2665 }
2651 case 0x5c: // D-MMU data in 2666 case 0x5c: // D-MMU data in
2652 - {  
2653 - unsigned int i;  
2654 -  
2655 - // Try finding an invalid entry  
2656 - for (i = 0; i < 64; i++) {  
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  
2665 - return;  
2666 - }  
2667 - }  
2668 - // Try finding an unlocked entry  
2669 - for (i = 0; i < 64; i++) {  
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  
2678 - return;  
2679 - }  
2680 - }  
2681 -#ifdef DEBUG_MMU  
2682 - DPRINTF_MMU("dmmu data map failed: no entries available\n");  
2683 -#endif  
2684 - // error state?  
2685 - return;  
2686 - } 2667 + replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
  2668 + return;
2687 case 0x5d: // D-MMU data access 2669 case 0x5d: // D-MMU data access
2688 { 2670 {
2689 unsigned int i = (addr >> 3) & 0x3f; 2671 unsigned int i = (addr >> 3) & 0x3f;
2690 2672
2691 - replace_tlb_entry(&env->dtlb[i], env,  
2692 - env->dmmu.tag_access, val); 2673 + replace_tlb_entry(&env->dtlb[i], env->dmmu.tag_access, val, env);
  2674 +
2693 #ifdef DEBUG_MMU 2675 #ifdef DEBUG_MMU
2694 - DPRINTF_MMU("dmmu data access replaced entry [%i]\n",  
2695 - i); 2676 + DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
2696 dump_mmu(env); 2677 dump_mmu(env);
2697 #endif 2678 #endif
2698 return; 2679 return;
2699 } 2680 }
2700 case 0x5f: // D-MMU demap 2681 case 0x5f: // D-MMU demap
2701 - demap_tlb(env->dtlb, val, env); 2682 + demap_tlb(env->dtlb, val, "dmmu", env);
2702 return; 2683 return;
2703 case 0x49: // Interrupt data receive 2684 case 0x49: // Interrupt data receive
2704 // XXX 2685 // XXX