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 | ... | ... |