Commit 6e8e7d4c092951f417297120e3d3cc28840a045b
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
Showing
4 changed files
with
225 additions
and
111 deletions
target-sparc/cpu.h
... | ... | @@ -273,6 +273,11 @@ enum { |
273 | 273 | }; |
274 | 274 | #endif |
275 | 275 | |
276 | +typedef struct SparcTLBEntry { | |
277 | + uint64_t tag; | |
278 | + uint64_t tte; | |
279 | +} SparcTLBEntry; | |
280 | + | |
276 | 281 | typedef struct CPUSPARCState { |
277 | 282 | target_ulong gregs[8]; /* general registers */ |
278 | 283 | target_ulong *regwptr; /* pointer to current register window */ |
... | ... | @@ -319,12 +324,33 @@ typedef struct CPUSPARCState { |
319 | 324 | uint64_t lsu; |
320 | 325 | #define DMMU_E 0x8 |
321 | 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 | 354 | uint32_t mmu_version; |
329 | 355 | #else |
330 | 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 | 386 | |
387 | 387 | // Returns true if TTE tag is valid and matches virtual address value in context |
388 | 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 | 390 | uint64_t address, uint64_t context, |
391 | 391 | target_phys_addr_t *physical) |
392 | 392 | { |
393 | 393 | uint64_t mask; |
394 | 394 | |
395 | - switch ((tlb_tte >> 61) & 3) { | |
395 | + switch ((tlb->tte >> 61) & 3) { | |
396 | 396 | default: |
397 | 397 | case 0x0: // 8k |
398 | 398 | mask = 0xffffffffffffe000ULL; |
... | ... | @@ -409,12 +409,12 @@ static inline int ultrasparc_tag_match(uint64_t tlb_tag, uint64_t tlb_tte, |
409 | 409 | } |
410 | 410 | |
411 | 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 | 416 | // decode physical address |
417 | - *physical = ((tlb_tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL; | |
417 | + *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL; | |
418 | 418 | return 1; |
419 | 419 | } |
420 | 420 | |
... | ... | @@ -434,21 +434,31 @@ static int get_physical_address_data(CPUState *env, |
434 | 434 | return 0; |
435 | 435 | } |
436 | 436 | |
437 | - context = env->dmmuregs[1] & 0x1fff; | |
437 | + context = env->dmmu.mmu_primary_context & 0x1fff; | |
438 | 438 | |
439 | 439 | for (i = 0; i < 64; i++) { |
440 | 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 | 442 | address, context, physical) |
443 | 443 | ) { |
444 | 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 | 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 | 462 | env->exception_index = TT_DFAULT; |
453 | 463 | #ifdef DEBUG_MMU |
454 | 464 | printf("DFAULT at 0x%" PRIx64 "\n", address); |
... | ... | @@ -456,7 +466,7 @@ static int get_physical_address_data(CPUState *env, |
456 | 466 | return 1; |
457 | 467 | } |
458 | 468 | *prot = PAGE_READ; |
459 | - if (env->dtlb_tte[i] & 0x2) | |
469 | + if (env->dtlb[i].tte & 0x2) | |
460 | 470 | *prot |= PAGE_WRITE; |
461 | 471 | return 0; |
462 | 472 | } |
... | ... | @@ -464,7 +474,7 @@ static int get_physical_address_data(CPUState *env, |
464 | 474 | #ifdef DEBUG_MMU |
465 | 475 | printf("DMISS at 0x%" PRIx64 "\n", address); |
466 | 476 | #endif |
467 | - env->dmmuregs[6] = (address & ~0x1fffULL) | context; | |
477 | + env->dmmu.tag_access = (address & ~0x1fffULL) | context; | |
468 | 478 | env->exception_index = TT_DMISS; |
469 | 479 | return 1; |
470 | 480 | } |
... | ... | @@ -483,19 +493,19 @@ static int get_physical_address_code(CPUState *env, |
483 | 493 | return 0; |
484 | 494 | } |
485 | 495 | |
486 | - context = env->dmmuregs[1] & 0x1fff; | |
496 | + context = env->dmmu.mmu_primary_context & 0x1fff; | |
487 | 497 | |
488 | 498 | for (i = 0; i < 64; i++) { |
489 | 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 | 501 | address, context, physical) |
492 | 502 | ) { |
493 | 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 | 507 | another fault) */ |
498 | - env->immuregs[3] |= (is_user << 3) | 1; | |
508 | + env->immu.sfsr |= (is_user << 3) | 1; | |
499 | 509 | env->exception_index = TT_TFAULT; |
500 | 510 | #ifdef DEBUG_MMU |
501 | 511 | printf("TFAULT at 0x%" PRIx64 "\n", address); |
... | ... | @@ -510,7 +520,7 @@ static int get_physical_address_code(CPUState *env, |
510 | 520 | printf("TMISS at 0x%" PRIx64 "\n", address); |
511 | 521 | #endif |
512 | 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 | 524 | env->exception_index = TT_TMISS; |
515 | 525 | return 1; |
516 | 526 | } |
... | ... | @@ -561,7 +571,7 @@ void dump_mmu(CPUState *env) |
561 | 571 | const char *mask; |
562 | 572 | |
563 | 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 | 575 | if ((env->lsu & DMMU_E) == 0) { |
566 | 576 | printf("DMMU disabled\n"); |
567 | 577 | } else { |
... | ... | @@ -583,8 +593,9 @@ void dump_mmu(CPUState *env) |
583 | 593 | break; |
584 | 594 | } |
585 | 595 | if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) { |
586 | - printf("VA: %" PRIx64 ", PA: %" PRIx64 | |
596 | + printf("[%02u] VA: " PRIx64 ", PA: " PRIx64 | |
587 | 597 | ", %s, %s, %s, %s, ctx %" PRId64 "\n", |
598 | + i, | |
588 | 599 | env->dtlb_tag[i] & (uint64_t)~0x1fffULL, |
589 | 600 | env->dtlb_tte[i] & (uint64_t)0x1ffffffe000ULL, |
590 | 601 | mask, |
... | ... | @@ -616,14 +627,15 @@ void dump_mmu(CPUState *env) |
616 | 627 | break; |
617 | 628 | } |
618 | 629 | if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) { |
619 | - printf("VA: %" PRIx64 ", PA: %" PRIx64 | |
630 | + printf("[%02u] VA: " PRIx64 ", PA: " PRIx64 | |
620 | 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 | 634 | env->itlb_tte[i] & (uint64_t)0x1ffffffe000ULL, |
623 | 635 | mask, |
624 | 636 | env->itlb_tte[i] & 0x4? "priv": "user", |
625 | 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 | 52 | qemu_put_be64s(f, &env->dmmuregs[i]); |
53 | 53 | } |
54 | 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 | 60 | qemu_put_be32s(f, &env->mmu_version); |
61 | 61 | for (i = 0; i < MAXTL_MAX; i++) { |
... | ... | @@ -148,10 +148,10 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) |
148 | 148 | qemu_get_be64s(f, &env->dmmuregs[i]); |
149 | 149 | } |
150 | 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 | 156 | qemu_get_be32s(f, &env->mmu_version); |
157 | 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 | 46 | int page_size) |
47 | 47 | { |
48 | 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 | 52 | // discard lower 13 bits which hold tag access context |
53 | 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 | 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 | 139 | #endif |
91 | 140 | |
92 | 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 | 2192 | |
2144 | 2193 | if (reg == 0) { |
2145 | 2194 | // I-TSB Tag Target register |
2146 | - ret = ultrasparc_tag_target(env->immuregs[6]); | |
2195 | + ret = ultrasparc_tag_target(env->immu.tag_access); | |
2147 | 2196 | } else { |
2148 | 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 | 2203 | { |
2155 | 2204 | // env->immuregs[5] holds I-MMU TSB register value |
2156 | 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 | 2207 | 8*1024); |
2159 | 2208 | break; |
2160 | 2209 | } |
... | ... | @@ -2162,7 +2211,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) |
2162 | 2211 | { |
2163 | 2212 | // env->immuregs[5] holds I-MMU TSB register value |
2164 | 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 | 2215 | 64*1024); |
2167 | 2216 | break; |
2168 | 2217 | } |
... | ... | @@ -2170,14 +2219,14 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) |
2170 | 2219 | { |
2171 | 2220 | int reg = (addr >> 3) & 0x3f; |
2172 | 2221 | |
2173 | - ret = env->itlb_tte[reg]; | |
2222 | + ret = env->itlb[reg].tte; | |
2174 | 2223 | break; |
2175 | 2224 | } |
2176 | 2225 | case 0x56: // I-MMU tag read |
2177 | 2226 | { |
2178 | 2227 | int reg = (addr >> 3) & 0x3f; |
2179 | 2228 | |
2180 | - ret = env->itlb_tag[reg]; | |
2229 | + ret = env->itlb[reg].tag; | |
2181 | 2230 | break; |
2182 | 2231 | } |
2183 | 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 | 2235 | |
2187 | 2236 | if (reg == 0) { |
2188 | 2237 | // D-TSB Tag Target register |
2189 | - ret = ultrasparc_tag_target(env->dmmuregs[6]); | |
2238 | + ret = ultrasparc_tag_target(env->dmmu.tag_access); | |
2190 | 2239 | } else { |
2191 | 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 | 2245 | { |
2197 | 2246 | // env->dmmuregs[5] holds D-MMU TSB register value |
2198 | 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 | 2249 | 8*1024); |
2201 | 2250 | break; |
2202 | 2251 | } |
... | ... | @@ -2204,7 +2253,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) |
2204 | 2253 | { |
2205 | 2254 | // env->dmmuregs[5] holds D-MMU TSB register value |
2206 | 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 | 2257 | 64*1024); |
2209 | 2258 | break; |
2210 | 2259 | } |
... | ... | @@ -2212,14 +2261,14 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) |
2212 | 2261 | { |
2213 | 2262 | int reg = (addr >> 3) & 0x3f; |
2214 | 2263 | |
2215 | - ret = env->dtlb_tte[reg]; | |
2264 | + ret = env->dtlb[reg].tte; | |
2216 | 2265 | break; |
2217 | 2266 | } |
2218 | 2267 | case 0x5e: // D-MMU tag read |
2219 | 2268 | { |
2220 | 2269 | int reg = (addr >> 3) & 0x3f; |
2221 | 2270 | |
2222 | - ret = env->dtlb_tag[reg]; | |
2271 | + ret = env->dtlb[reg].tag; | |
2223 | 2272 | break; |
2224 | 2273 | } |
2225 | 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 | 2511 | oldreg = env->immuregs[reg]; |
2463 | 2512 | switch(reg) { |
2464 | 2513 | case 0: // RO |
2465 | - case 4: | |
2466 | 2514 | return; |
2467 | 2515 | case 1: // Not in I-MMU |
2468 | 2516 | case 2: |
2469 | - case 7: | |
2470 | - case 8: | |
2471 | 2517 | return; |
2472 | 2518 | case 3: // SFSR |
2473 | 2519 | if ((val & 1) == 0) |
2474 | 2520 | val = 0; // Clear SFSR |
2521 | + env->immu.sfsr = val; | |
2475 | 2522 | break; |
2523 | + case 4: // RO | |
2524 | + return; | |
2476 | 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 | 2530 | case 6: // Tag access |
2531 | + env->immu.tag_access = val; | |
2532 | + break; | |
2533 | + case 7: | |
2534 | + case 8: | |
2535 | + return; | |
2478 | 2536 | default: |
2479 | 2537 | break; |
2480 | 2538 | } |
2481 | - env->immuregs[reg] = val; | |
2539 | + | |
2482 | 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 | 2542 | PRIx64 "\n", reg, oldreg, env->immuregs[reg]); |
2485 | 2543 | } |
2486 | 2544 | #ifdef DEBUG_MMU |
... | ... | @@ -2494,20 +2552,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) |
2494 | 2552 | |
2495 | 2553 | // Try finding an invalid entry |
2496 | 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 | 2563 | return; |
2501 | 2564 | } |
2502 | 2565 | } |
2503 | 2566 | // Try finding an unlocked entry |
2504 | 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 | 2576 | return; |
2509 | 2577 | } |
2510 | 2578 | } |
2579 | +#ifdef DEBUG_MMU | |
2580 | + DPRINTF_MMU("immu data map failed: no entries available\n"); | |
2581 | +#endif | |
2511 | 2582 | // error state? |
2512 | 2583 | return; |
2513 | 2584 | } |
... | ... | @@ -2517,27 +2588,18 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) |
2517 | 2588 | |
2518 | 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 | 2599 | return; |
2523 | 2600 | } |
2524 | 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 | 2603 | return; |
2542 | 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 | 2614 | case 3: // SFSR |
2553 | 2615 | if ((val & 1) == 0) { |
2554 | 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 | 2620 | break; |
2559 | 2621 | case 1: // Primary context |
2622 | + env->dmmu.mmu_primary_context = val; | |
2623 | + break; | |
2560 | 2624 | case 2: // Secondary context |
2625 | + env->dmmu.mmu_secondary_context = val; | |
2626 | + break; | |
2561 | 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 | 2632 | case 6: // Tag access |
2633 | + env->dmmu.tag_access = val; | |
2634 | + break; | |
2563 | 2635 | case 7: // Virtual Watchpoint |
2564 | 2636 | case 8: // Physical Watchpoint |
2565 | 2637 | default: |
2638 | + env->dmmuregs[reg] = val; | |
2566 | 2639 | break; |
2567 | 2640 | } |
2568 | - env->dmmuregs[reg] = val; | |
2641 | + | |
2569 | 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 | 2644 | PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]); |
2572 | 2645 | } |
2573 | 2646 | #ifdef DEBUG_MMU |
... | ... | @@ -2581,20 +2654,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) |
2581 | 2654 | |
2582 | 2655 | // Try finding an invalid entry |
2583 | 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 | 2665 | return; |
2588 | 2666 | } |
2589 | 2667 | } |
2590 | 2668 | // Try finding an unlocked entry |
2591 | 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 | 2678 | return; |
2596 | 2679 | } |
2597 | 2680 | } |
2681 | +#ifdef DEBUG_MMU | |
2682 | + DPRINTF_MMU("dmmu data map failed: no entries available\n"); | |
2683 | +#endif | |
2598 | 2684 | // error state? |
2599 | 2685 | return; |
2600 | 2686 | } |
... | ... | @@ -2602,27 +2688,17 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) |
2602 | 2688 | { |
2603 | 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 | 2698 | return; |
2608 | 2699 | } |
2609 | 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 | 2702 | return; |
2627 | 2703 | case 0x49: // Interrupt data receive |
2628 | 2704 | // XXX | ... | ... |