Revision d12d51d5 target-ppc/helper.c
b/target-ppc/helper.c | ||
---|---|---|
39 | 39 |
//#define DEBUG_EXCEPTIONS |
40 | 40 |
//#define FLUSH_ALL_TLBS |
41 | 41 |
|
42 |
#ifdef DEBUG_MMU |
|
43 |
# define LOG_MMU(...) do { \ |
|
44 |
if (loglevel) \ |
|
45 |
fprintf(logfile, ## __VA_ARGS__); \ |
|
46 |
} while (0) |
|
47 |
# define LOG_MMU_STATE(env) do { \ |
|
48 |
if (loglevel) \ |
|
49 |
cpu_dump_state(env, logfile, fprintf, 0); \ |
|
50 |
} while (0) |
|
51 |
#else |
|
52 |
# define LOG_MMU(...) do { } while (0) |
|
53 |
# define LOG_MMU_STATE(...) do { } while (0) |
|
54 |
#endif |
|
55 |
|
|
56 |
|
|
57 |
#ifdef DEBUG_SOFTWARE_TLB |
|
58 |
# define LOG_SWTLB(...) do { \ |
|
59 |
if (loglevel) \ |
|
60 |
fprintf(logfile, ## __VA_ARGS__); \ |
|
61 |
} while (0) |
|
62 |
#else |
|
63 |
# define LOG_SWTLB(...) do { } while (0) |
|
64 |
#endif |
|
65 |
|
|
66 |
#ifdef DEBUG_BATS |
|
67 |
# define LOG_BATS(...) do { \ |
|
68 |
if (loglevel) \ |
|
69 |
fprintf(logfile, ## __VA_ARGS__); \ |
|
70 |
} while (0) |
|
71 |
#else |
|
72 |
# define LOG_BATS(...) do { } while (0) |
|
73 |
#endif |
|
74 |
|
|
75 |
#ifdef DEBUG_SLB |
|
76 |
# define LOG_SLB(...) do { \ |
|
77 |
if (loglevel) \ |
|
78 |
fprintf(logfile, ## __VA_ARGS__); \ |
|
79 |
} while (0) |
|
80 |
#else |
|
81 |
# define LOG_SLB(...) do { } while (0) |
|
82 |
#endif |
|
83 |
|
|
84 |
#ifdef DEBUG_EXCEPTIONS |
|
85 |
# define LOG_EXCP(...) do { \ |
|
86 |
if (loglevel) \ |
|
87 |
fprintf(logfile, ## __VA_ARGS__); \ |
|
88 |
} while (0) |
|
89 |
#else |
|
90 |
# define LOG_EXCP(...) do { } while (0) |
|
91 |
#endif |
|
92 |
|
|
93 |
|
|
42 | 94 |
/*****************************************************************************/ |
43 | 95 |
/* PowerPC MMU emulation */ |
44 | 96 |
|
... | ... | |
218 | 270 |
ret = check_prot(ctx->prot, rw, type); |
219 | 271 |
if (ret == 0) { |
220 | 272 |
/* Access granted */ |
221 |
#if defined (DEBUG_MMU) |
|
222 |
if (loglevel != 0) |
|
223 |
fprintf(logfile, "PTE access granted !\n"); |
|
224 |
#endif |
|
273 |
LOG_MMU("PTE access granted !\n"); |
|
225 | 274 |
} else { |
226 | 275 |
/* Access right violation */ |
227 |
#if defined (DEBUG_MMU) |
|
228 |
if (loglevel != 0) |
|
229 |
fprintf(logfile, "PTE access rejected\n"); |
|
230 |
#endif |
|
276 |
LOG_MMU("PTE access rejected\n"); |
|
231 | 277 |
} |
232 | 278 |
} |
233 | 279 |
} |
... | ... | |
298 | 344 |
ppc6xx_tlb_t *tlb; |
299 | 345 |
int nr, max; |
300 | 346 |
|
301 |
#if defined (DEBUG_SOFTWARE_TLB) && 0 |
|
302 |
if (loglevel != 0) { |
|
303 |
fprintf(logfile, "Invalidate all TLBs\n"); |
|
304 |
} |
|
305 |
#endif |
|
347 |
//LOG_SWTLB("Invalidate all TLBs\n"); |
|
306 | 348 |
/* Invalidate all defined software TLB */ |
307 | 349 |
max = env->nb_tlb; |
308 | 350 |
if (env->id_tlbs == 1) |
... | ... | |
328 | 370 |
nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code); |
329 | 371 |
tlb = &env->tlb[nr].tlb6; |
330 | 372 |
if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) { |
331 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
332 |
if (loglevel != 0) { |
|
333 |
fprintf(logfile, "TLB invalidate %d/%d " ADDRX "\n", |
|
373 |
LOG_SWTLB("TLB invalidate %d/%d " ADDRX "\n", |
|
334 | 374 |
nr, env->nb_tlb, eaddr); |
335 |
} |
|
336 |
#endif |
|
337 | 375 |
pte_invalidate(&tlb->pte0); |
338 | 376 |
tlb_flush_page(env, tlb->EPN); |
339 | 377 |
} |
... | ... | |
359 | 397 |
|
360 | 398 |
nr = ppc6xx_tlb_getnum(env, EPN, way, is_code); |
361 | 399 |
tlb = &env->tlb[nr].tlb6; |
362 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
363 |
if (loglevel != 0) { |
|
364 |
fprintf(logfile, "Set TLB %d/%d EPN " ADDRX " PTE0 " ADDRX |
|
400 |
LOG_SWTLB("Set TLB %d/%d EPN " ADDRX " PTE0 " ADDRX |
|
365 | 401 |
" PTE1 " ADDRX "\n", nr, env->nb_tlb, EPN, pte0, pte1); |
366 |
} |
|
367 |
#endif |
|
368 | 402 |
/* Invalidate any pending reference in Qemu for this virtual address */ |
369 | 403 |
__ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1); |
370 | 404 |
tlb->pte0 = pte0; |
... | ... | |
390 | 424 |
tlb = &env->tlb[nr].tlb6; |
391 | 425 |
/* This test "emulates" the PTE index match for hardware TLBs */ |
392 | 426 |
if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) { |
393 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
394 |
if (loglevel != 0) { |
|
395 |
fprintf(logfile, "TLB %d/%d %s [" ADDRX " " ADDRX |
|
427 |
LOG_SWTLB("TLB %d/%d %s [" ADDRX " " ADDRX |
|
396 | 428 |
"] <> " ADDRX "\n", |
397 | 429 |
nr, env->nb_tlb, |
398 | 430 |
pte_is_valid(tlb->pte0) ? "valid" : "inval", |
399 | 431 |
tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr); |
400 |
} |
|
401 |
#endif |
|
402 | 432 |
continue; |
403 | 433 |
} |
404 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
405 |
if (loglevel != 0) { |
|
406 |
fprintf(logfile, "TLB %d/%d %s " ADDRX " <> " ADDRX " " ADDRX |
|
434 |
LOG_SWTLB("TLB %d/%d %s " ADDRX " <> " ADDRX " " ADDRX |
|
407 | 435 |
" %c %c\n", |
408 | 436 |
nr, env->nb_tlb, |
409 | 437 |
pte_is_valid(tlb->pte0) ? "valid" : "inval", |
410 | 438 |
tlb->EPN, eaddr, tlb->pte1, |
411 | 439 |
rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D'); |
412 |
} |
|
413 |
#endif |
|
414 | 440 |
switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) { |
415 | 441 |
case -3: |
416 | 442 |
/* TLB inconsistency */ |
... | ... | |
437 | 463 |
} |
438 | 464 |
if (best != -1) { |
439 | 465 |
done: |
440 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
441 |
if (loglevel != 0) { |
|
442 |
fprintf(logfile, "found TLB at addr " PADDRX " prot=%01x ret=%d\n", |
|
466 |
LOG_SWTLB("found TLB at addr " PADDRX " prot=%01x ret=%d\n", |
|
443 | 467 |
ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret); |
444 |
} |
|
445 |
#endif |
|
446 | 468 |
/* Update page flags */ |
447 | 469 |
pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw); |
448 | 470 |
} |
... | ... | |
485 | 507 |
int key, pp, valid, prot; |
486 | 508 |
|
487 | 509 |
bl = (*BATl & 0x0000003F) << 17; |
488 |
#if defined (DEBUG_BATS) |
|
489 |
if (loglevel != 0) { |
|
490 |
fprintf(logfile, "b %02x ==> bl " ADDRX " msk " ADDRX "\n", |
|
510 |
LOG_BATS("b %02x ==> bl " ADDRX " msk " ADDRX "\n", |
|
491 | 511 |
(uint8_t)(*BATl & 0x0000003F), bl, ~bl); |
492 |
} |
|
493 |
#endif |
|
494 | 512 |
prot = 0; |
495 | 513 |
valid = (*BATl >> 6) & 1; |
496 | 514 |
if (valid) { |
... | ... | |
514 | 532 |
int i, valid, prot; |
515 | 533 |
int ret = -1; |
516 | 534 |
|
517 |
#if defined (DEBUG_BATS) |
|
518 |
if (loglevel != 0) { |
|
519 |
fprintf(logfile, "%s: %cBAT v " ADDRX "\n", __func__, |
|
535 |
LOG_BATS("%s: %cBAT v " ADDRX "\n", __func__, |
|
520 | 536 |
type == ACCESS_CODE ? 'I' : 'D', virtual); |
521 |
} |
|
522 |
#endif |
|
523 | 537 |
switch (type) { |
524 | 538 |
case ACCESS_CODE: |
525 | 539 |
BATlt = env->IBAT[1]; |
... | ... | |
541 | 555 |
} else { |
542 | 556 |
bat_size_prot(env, &bl, &valid, &prot, BATu, BATl); |
543 | 557 |
} |
544 |
#if defined (DEBUG_BATS) |
|
545 |
if (loglevel != 0) { |
|
546 |
fprintf(logfile, "%s: %cBAT%d v " ADDRX " BATu " ADDRX |
|
558 |
LOG_BATS("%s: %cBAT%d v " ADDRX " BATu " ADDRX |
|
547 | 559 |
" BATl " ADDRX "\n", __func__, |
548 | 560 |
type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl); |
549 |
} |
|
550 |
#endif |
|
551 | 561 |
if ((virtual & 0xF0000000) == BEPIu && |
552 | 562 |
((virtual & 0x0FFE0000) & ~bl) == BEPIl) { |
553 | 563 |
/* BAT matches */ |
... | ... | |
559 | 569 |
/* Compute access rights */ |
560 | 570 |
ctx->prot = prot; |
561 | 571 |
ret = check_prot(ctx->prot, rw, type); |
562 |
#if defined (DEBUG_BATS) |
|
563 |
if (ret == 0 && loglevel != 0) { |
|
564 |
fprintf(logfile, "BAT %d match: r " PADDRX " prot=%c%c\n", |
|
565 |
i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-', |
|
566 |
ctx->prot & PAGE_WRITE ? 'W' : '-'); |
|
567 |
} |
|
568 |
#endif |
|
572 |
if (ret == 0) |
|
573 |
LOG_BATS("BAT %d match: r " PADDRX " prot=%c%c\n", |
|
574 |
i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-', |
|
575 |
ctx->prot & PAGE_WRITE ? 'W' : '-'); |
|
569 | 576 |
break; |
570 | 577 |
} |
571 | 578 |
} |
572 | 579 |
} |
573 | 580 |
if (ret < 0) { |
574 |
#if defined (DEBUG_BATS)
|
|
575 |
if (loglevel != 0) {
|
|
576 |
fprintf(logfile, "no BAT match for " ADDRX ":\n", virtual);
|
|
581 |
#if defined(DEBUG_BATS) |
|
582 |
if (IS_LOGGING) {
|
|
583 |
QEMU_LOG0("no BAT match for " ADDRX ":\n", virtual);
|
|
577 | 584 |
for (i = 0; i < 4; i++) { |
578 | 585 |
BATu = &BATut[i]; |
579 | 586 |
BATl = &BATlt[i]; |
580 | 587 |
BEPIu = *BATu & 0xF0000000; |
581 | 588 |
BEPIl = *BATu & 0x0FFE0000; |
582 | 589 |
bl = (*BATu & 0x00001FFC) << 15; |
583 |
fprintf(logfile, "%s: %cBAT%d v " ADDRX " BATu " ADDRX
|
|
590 |
QEMU_LOG0("%s: %cBAT%d v " ADDRX " BATu " ADDRX
|
|
584 | 591 |
" BATl " ADDRX " \n\t" ADDRX " " ADDRX " " ADDRX "\n", |
585 | 592 |
__func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual, |
586 | 593 |
*BATu, *BATl, BEPIu, BEPIl, bl); |
... | ... | |
588 | 595 |
} |
589 | 596 |
#endif |
590 | 597 |
} |
591 |
|
|
592 | 598 |
/* No hit */ |
593 | 599 |
return ret; |
594 | 600 |
} |
... | ... | |
609 | 615 |
pte0 = ldq_phys(base + (i * 16)); |
610 | 616 |
pte1 = ldq_phys(base + (i * 16) + 8); |
611 | 617 |
r = pte64_check(ctx, pte0, pte1, h, rw, type); |
612 |
#if defined (DEBUG_MMU) |
|
613 |
if (loglevel != 0) { |
|
614 |
fprintf(logfile, "Load pte from " ADDRX " => " ADDRX " " ADDRX |
|
618 |
LOG_MMU("Load pte from " ADDRX " => " ADDRX " " ADDRX |
|
615 | 619 |
" %d %d %d " ADDRX "\n", |
616 | 620 |
base + (i * 16), pte0, pte1, |
617 | 621 |
(int)(pte0 & 1), h, (int)((pte0 >> 1) & 1), |
618 | 622 |
ctx->ptem); |
619 |
} |
|
620 |
#endif |
|
621 | 623 |
} else |
622 | 624 |
#endif |
623 | 625 |
{ |
624 | 626 |
pte0 = ldl_phys(base + (i * 8)); |
625 | 627 |
pte1 = ldl_phys(base + (i * 8) + 4); |
626 | 628 |
r = pte32_check(ctx, pte0, pte1, h, rw, type); |
627 |
#if defined (DEBUG_MMU) |
|
628 |
if (loglevel != 0) { |
|
629 |
fprintf(logfile, "Load pte from " ADDRX " => " ADDRX " " ADDRX |
|
629 |
LOG_MMU("Load pte from " ADDRX " => " ADDRX " " ADDRX |
|
630 | 630 |
" %d %d %d " ADDRX "\n", |
631 | 631 |
base + (i * 8), pte0, pte1, |
632 | 632 |
(int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1), |
633 | 633 |
ctx->ptem); |
634 |
} |
|
635 |
#endif |
|
636 | 634 |
} |
637 | 635 |
switch (r) { |
638 | 636 |
case -3: |
... | ... | |
660 | 658 |
} |
661 | 659 |
if (good != -1) { |
662 | 660 |
done: |
663 |
#if defined (DEBUG_MMU) |
|
664 |
if (loglevel != 0) { |
|
665 |
fprintf(logfile, "found PTE at addr " PADDRX " prot=%01x ret=%d\n", |
|
661 |
LOG_MMU("found PTE at addr " PADDRX " prot=%01x ret=%d\n", |
|
666 | 662 |
ctx->raddr, ctx->prot, ret); |
667 |
} |
|
668 |
#endif |
|
669 | 663 |
/* Update page flags */ |
670 | 664 |
pte1 = ctx->raddr; |
671 | 665 |
if (pte_update_flags(ctx, &pte1, ret, rw) == 1) { |
... | ... | |
729 | 723 |
|
730 | 724 |
ret = -5; |
731 | 725 |
sr_base = env->spr[SPR_ASR]; |
732 |
#if defined(DEBUG_SLB) |
|
733 |
if (loglevel != 0) { |
|
734 |
fprintf(logfile, "%s: eaddr " ADDRX " base " PADDRX "\n", |
|
726 |
LOG_SLB("%s: eaddr " ADDRX " base " PADDRX "\n", |
|
735 | 727 |
__func__, eaddr, sr_base); |
736 |
} |
|
737 |
#endif |
|
738 | 728 |
mask = 0x0000000000000000ULL; /* Avoid gcc warning */ |
739 | 729 |
for (n = 0; n < env->slb_nr; n++) { |
740 | 730 |
tmp64 = ldq_phys(sr_base); |
741 | 731 |
tmp = ldl_phys(sr_base + 8); |
742 |
#if defined(DEBUG_SLB) |
|
743 |
if (loglevel != 0) { |
|
744 |
fprintf(logfile, "%s: seg %d " PADDRX " %016" PRIx64 " %08" |
|
732 |
LOG_SLB("%s: seg %d " PADDRX " %016" PRIx64 " %08" |
|
745 | 733 |
PRIx32 "\n", __func__, n, sr_base, tmp64, tmp); |
746 |
} |
|
747 |
#endif |
|
748 | 734 |
if (slb_is_valid(tmp64)) { |
749 | 735 |
/* SLB entry is valid */ |
750 | 736 |
switch (tmp64 & 0x0000000006000000ULL) { |
... | ... | |
848 | 834 |
} else { |
849 | 835 |
rt = 0; |
850 | 836 |
} |
851 |
#if defined(DEBUG_SLB) |
|
852 |
if (loglevel != 0) { |
|
853 |
fprintf(logfile, "%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d " |
|
837 |
LOG_SLB("%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d " |
|
854 | 838 |
ADDRX "\n", __func__, sr_base, tmp64, tmp, slb_nr, rt); |
855 |
} |
|
856 |
#endif |
|
857 | 839 |
|
858 | 840 |
return rt; |
859 | 841 |
} |
... | ... | |
875 | 857 |
tmp64 |= 1 << 27; |
876 | 858 |
/* Set ESID */ |
877 | 859 |
tmp64 |= (uint32_t)slb_nr << 28; |
878 |
#if defined(DEBUG_SLB) |
|
879 |
if (loglevel != 0) { |
|
880 |
fprintf(logfile, "%s: %d " ADDRX " => " PADDRX " %016" PRIx64 |
|
860 |
LOG_SLB("%s: %d " ADDRX " => " PADDRX " %016" PRIx64 |
|
881 | 861 |
" %08" PRIx32 "\n", __func__, |
882 | 862 |
slb_nr, rs, sr_base, tmp64, tmp); |
883 |
} |
|
884 |
#endif |
|
885 | 863 |
/* Write SLB entry to memory */ |
886 | 864 |
stq_phys(sr_base, tmp64); |
887 | 865 |
stl_phys(sr_base + 8, tmp); |
... | ... | |
911 | 889 |
pr = msr_pr; |
912 | 890 |
#if defined(TARGET_PPC64) |
913 | 891 |
if (env->mmu_model & POWERPC_MMU_64) { |
914 |
#if defined (DEBUG_MMU) |
|
915 |
if (loglevel != 0) { |
|
916 |
fprintf(logfile, "Check SLBs\n"); |
|
917 |
} |
|
918 |
#endif |
|
892 |
LOG_MMU("Check SLBs\n"); |
|
919 | 893 |
ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr); |
920 | 894 |
if (ret < 0) |
921 | 895 |
return ret; |
... | ... | |
941 | 915 |
vsid_sh = 6; |
942 | 916 |
sdr_sh = 16; |
943 | 917 |
sdr_mask = 0xFFC0; |
944 |
#if defined (DEBUG_MMU) |
|
945 |
if (loglevel != 0) { |
|
946 |
fprintf(logfile, "Check segment v=" ADDRX " %d " ADDRX |
|
918 |
LOG_MMU("Check segment v=" ADDRX " %d " ADDRX |
|
947 | 919 |
" nip=" ADDRX " lr=" ADDRX " ir=%d dr=%d pr=%d %d t=%d\n", |
948 | 920 |
eaddr, (int)(eaddr >> 28), sr, env->nip, |
949 | 921 |
env->lr, (int)msr_ir, (int)msr_dr, pr != 0 ? 1 : 0, |
950 | 922 |
rw, type); |
951 |
} |
|
952 |
#endif |
|
953 | 923 |
} |
954 |
#if defined (DEBUG_MMU) |
|
955 |
if (loglevel != 0) { |
|
956 |
fprintf(logfile, "pte segment: key=%d ds %d nx %d vsid " ADDRX "\n", |
|
924 |
LOG_MMU("pte segment: key=%d ds %d nx %d vsid " ADDRX "\n", |
|
957 | 925 |
ctx->key, ds, ctx->nx, vsid); |
958 |
} |
|
959 |
#endif |
|
960 | 926 |
ret = -1; |
961 | 927 |
if (!ds) { |
962 | 928 |
/* Check if instruction fetch is allowed, if needed */ |
... | ... | |
977 | 943 |
hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask; |
978 | 944 |
} |
979 | 945 |
mask = (htab_mask << sdr_sh) | sdr_mask; |
980 |
#if defined (DEBUG_MMU) |
|
981 |
if (loglevel != 0) { |
|
982 |
fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX |
|
946 |
LOG_MMU("sdr " PADDRX " sh %d hash " PADDRX |
|
983 | 947 |
" mask " PADDRX " " ADDRX "\n", |
984 | 948 |
sdr, sdr_sh, hash, mask, page_mask); |
985 |
} |
|
986 |
#endif |
|
987 | 949 |
ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask); |
988 | 950 |
/* Secondary table address */ |
989 | 951 |
hash = (~hash) & vsid_mask; |
990 |
#if defined (DEBUG_MMU) |
|
991 |
if (loglevel != 0) { |
|
992 |
fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX |
|
952 |
LOG_MMU("sdr " PADDRX " sh %d hash " PADDRX |
|
993 | 953 |
" mask " PADDRX "\n", |
994 | 954 |
sdr, sdr_sh, hash, mask); |
995 |
} |
|
996 |
#endif |
|
997 | 955 |
ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask); |
998 | 956 |
#if defined(TARGET_PPC64) |
999 | 957 |
if (env->mmu_model & POWERPC_MMU_64) { |
... | ... | |
1011 | 969 |
/* Software TLB search */ |
1012 | 970 |
ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type); |
1013 | 971 |
} else { |
1014 |
#if defined (DEBUG_MMU) |
|
1015 |
if (loglevel != 0) { |
|
1016 |
fprintf(logfile, "0 sdr1=" PADDRX " vsid=" ADDRX " " |
|
972 |
LOG_MMU("0 sdr1=" PADDRX " vsid=" ADDRX " " |
|
1017 | 973 |
"api=" ADDRX " hash=" PADDRX |
1018 | 974 |
" pg_addr=" PADDRX "\n", |
1019 | 975 |
sdr, vsid, pgidx, hash, ctx->pg_addr[0]); |
1020 |
} |
|
1021 |
#endif |
|
1022 | 976 |
/* Primary table lookup */ |
1023 | 977 |
ret = find_pte(env, ctx, 0, rw, type); |
1024 | 978 |
if (ret < 0) { |
1025 | 979 |
/* Secondary table lookup */ |
1026 |
#if defined (DEBUG_MMU) |
|
1027 |
if (eaddr != 0xEFFFFFFF && loglevel != 0) { |
|
1028 |
fprintf(logfile, "1 sdr1=" PADDRX " vsid=" ADDRX " " |
|
980 |
if (eaddr != 0xEFFFFFFF) |
|
981 |
LOG_MMU("1 sdr1=" PADDRX " vsid=" ADDRX " " |
|
1029 | 982 |
"api=" ADDRX " hash=" PADDRX |
1030 | 983 |
" pg_addr=" PADDRX "\n", |
1031 | 984 |
sdr, vsid, pgidx, hash, ctx->pg_addr[1]); |
1032 |
} |
|
1033 |
#endif |
|
1034 | 985 |
ret2 = find_pte(env, ctx, 1, rw, type); |
1035 | 986 |
if (ret2 != -1) |
1036 | 987 |
ret = ret2; |
... | ... | |
1056 | 1007 |
} |
1057 | 1008 |
#endif |
1058 | 1009 |
} else { |
1059 |
#if defined (DEBUG_MMU) |
|
1060 |
if (loglevel != 0) |
|
1061 |
fprintf(logfile, "No access allowed\n"); |
|
1062 |
#endif |
|
1010 |
LOG_MMU("No access allowed\n"); |
|
1063 | 1011 |
ret = -3; |
1064 | 1012 |
} |
1065 | 1013 |
} else { |
1066 |
#if defined (DEBUG_MMU) |
|
1067 |
if (loglevel != 0) |
|
1068 |
fprintf(logfile, "direct store...\n"); |
|
1069 |
#endif |
|
1014 |
LOG_MMU("direct store...\n"); |
|
1070 | 1015 |
/* Direct-store segment : absolutely *BUGGY* for now */ |
1071 | 1016 |
switch (type) { |
1072 | 1017 |
case ACCESS_INT: |
... | ... | |
1124 | 1069 |
return -1; |
1125 | 1070 |
} |
1126 | 1071 |
mask = ~(tlb->size - 1); |
1127 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
1128 |
if (loglevel != 0) { |
|
1129 |
fprintf(logfile, "%s: TLB %d address " ADDRX " PID %u <=> " ADDRX |
|
1072 |
LOG_SWTLB("%s: TLB %d address " ADDRX " PID %u <=> " ADDRX |
|
1130 | 1073 |
" " ADDRX " %u\n", |
1131 | 1074 |
__func__, i, address, pid, tlb->EPN, mask, (uint32_t)tlb->PID); |
1132 |
} |
|
1133 |
#endif |
|
1134 | 1075 |
/* Check PID */ |
1135 | 1076 |
if (tlb->PID != 0 && tlb->PID != pid) |
1136 | 1077 |
return -1; |
... | ... | |
1223 | 1164 |
continue; |
1224 | 1165 |
zsel = (tlb->attr >> 4) & 0xF; |
1225 | 1166 |
zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3; |
1226 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
1227 |
if (loglevel != 0) { |
|
1228 |
fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n", |
|
1167 |
LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n", |
|
1229 | 1168 |
__func__, i, zsel, zpr, rw, tlb->attr); |
1230 |
} |
|
1231 |
#endif |
|
1232 | 1169 |
/* Check execute enable bit */ |
1233 | 1170 |
switch (zpr) { |
1234 | 1171 |
case 0x2: |
... | ... | |
1258 | 1195 |
} |
1259 | 1196 |
if (ret >= 0) { |
1260 | 1197 |
ctx->raddr = raddr; |
1261 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
1262 |
if (loglevel != 0) { |
|
1263 |
fprintf(logfile, "%s: access granted " ADDRX " => " PADDRX |
|
1198 |
LOG_SWTLB("%s: access granted " ADDRX " => " PADDRX |
|
1264 | 1199 |
" %d %d\n", __func__, address, ctx->raddr, ctx->prot, |
1265 | 1200 |
ret); |
1266 |
} |
|
1267 |
#endif |
|
1268 | 1201 |
return 0; |
1269 | 1202 |
} |
1270 | 1203 |
} |
1271 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
1272 |
if (loglevel != 0) { |
|
1273 |
fprintf(logfile, "%s: access refused " ADDRX " => " PADDRX |
|
1204 |
LOG_SWTLB("%s: access refused " ADDRX " => " PADDRX |
|
1274 | 1205 |
" %d %d\n", __func__, address, raddr, ctx->prot, |
1275 | 1206 |
ret); |
1276 |
} |
|
1277 |
#endif |
|
1278 | 1207 |
|
1279 | 1208 |
return ret; |
1280 | 1209 |
} |
... | ... | |
1500 | 1429 |
ctx.raddr & TARGET_PAGE_MASK, ctx.prot, |
1501 | 1430 |
mmu_idx, is_softmmu); |
1502 | 1431 |
} else if (ret < 0) { |
1503 |
#if defined (DEBUG_MMU) |
|
1504 |
if (loglevel != 0) |
|
1505 |
cpu_dump_state(env, logfile, fprintf, 0); |
|
1506 |
#endif |
|
1432 |
LOG_MMU_STATE(env); |
|
1507 | 1433 |
if (access_type == ACCESS_CODE) { |
1508 | 1434 |
switch (ret) { |
1509 | 1435 |
case -1: |
... | ... | |
1753 | 1679 |
|
1754 | 1680 |
base = BATu & ~0x0001FFFF; |
1755 | 1681 |
end = base + mask + 0x00020000; |
1756 |
#if defined (DEBUG_BATS) |
|
1757 |
if (loglevel != 0) { |
|
1758 |
fprintf(logfile, "Flush BAT from " ADDRX " to " ADDRX " (" ADDRX ")\n", |
|
1682 |
LOG_BATS("Flush BAT from " ADDRX " to " ADDRX " (" ADDRX ")\n", |
|
1759 | 1683 |
base, end, mask); |
1760 |
} |
|
1761 |
#endif |
|
1762 | 1684 |
for (page = base; page != end; page += TARGET_PAGE_SIZE) |
1763 | 1685 |
tlb_flush_page(env, page); |
1764 |
#if defined (DEBUG_BATS) |
|
1765 |
if (loglevel != 0) |
|
1766 |
fprintf(logfile, "Flush done\n"); |
|
1767 |
#endif |
|
1686 |
LOG_BATS("Flush done\n"); |
|
1768 | 1687 |
} |
1769 | 1688 |
#endif |
1770 | 1689 |
|
1771 | 1690 |
static always_inline void dump_store_bat (CPUPPCState *env, char ID, |
1772 | 1691 |
int ul, int nr, target_ulong value) |
1773 | 1692 |
{ |
1774 |
#if defined (DEBUG_BATS) |
|
1775 |
if (loglevel != 0) { |
|
1776 |
fprintf(logfile, "Set %cBAT%d%c to " ADDRX " (" ADDRX ")\n", |
|
1693 |
LOG_BATS("Set %cBAT%d%c to " ADDRX " (" ADDRX ")\n", |
|
1777 | 1694 |
ID, nr, ul == 0 ? 'u' : 'l', value, env->nip); |
1778 |
} |
|
1779 |
#endif |
|
1780 | 1695 |
} |
1781 | 1696 |
|
1782 | 1697 |
void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value) |
... | ... | |
2046 | 1961 |
|
2047 | 1962 |
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value) |
2048 | 1963 |
{ |
2049 |
#if defined (DEBUG_MMU) |
|
2050 |
if (loglevel != 0) { |
|
2051 |
fprintf(logfile, "%s: " ADDRX "\n", __func__, value); |
|
2052 |
} |
|
2053 |
#endif |
|
1964 |
LOG_MMU("%s: " ADDRX "\n", __func__, value); |
|
2054 | 1965 |
if (env->sdr1 != value) { |
2055 | 1966 |
/* XXX: for PowerPC 64, should check that the HTABSIZE value |
2056 | 1967 |
* is <= 28 |
... | ... | |
2062 | 1973 |
|
2063 | 1974 |
void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value) |
2064 | 1975 |
{ |
2065 |
#if defined (DEBUG_MMU) |
|
2066 |
if (loglevel != 0) { |
|
2067 |
fprintf(logfile, "%s: reg=%d " ADDRX " " ADDRX "\n", |
|
1976 |
LOG_MMU("%s: reg=%d " ADDRX " " ADDRX "\n", |
|
2068 | 1977 |
__func__, srnum, value, env->sr[srnum]); |
2069 |
} |
|
2070 |
#endif |
|
2071 | 1978 |
if (env->sr[srnum] != value) { |
2072 | 1979 |
env->sr[srnum] = value; |
2073 | 1980 |
#if !defined(FLUSH_ALL_TLBS) && 0 |
... | ... | |
2205 | 2112 |
} |
2206 | 2113 |
goto store_next; |
2207 | 2114 |
case POWERPC_EXCP_DSI: /* Data storage exception */ |
2208 |
#if defined (DEBUG_EXCEPTIONS) |
|
2209 |
if (loglevel != 0) { |
|
2210 |
fprintf(logfile, "DSI exception: DSISR=" ADDRX" DAR=" ADDRX "\n", |
|
2115 |
LOG_EXCP("DSI exception: DSISR=" ADDRX" DAR=" ADDRX "\n", |
|
2211 | 2116 |
env->spr[SPR_DSISR], env->spr[SPR_DAR]); |
2212 |
} |
|
2213 |
#endif |
|
2214 | 2117 |
new_msr &= ~((target_ulong)1 << MSR_RI); |
2215 | 2118 |
if (lpes1 == 0) |
2216 | 2119 |
new_msr |= (target_ulong)MSR_HVB; |
2217 | 2120 |
goto store_next; |
2218 | 2121 |
case POWERPC_EXCP_ISI: /* Instruction storage exception */ |
2219 |
#if defined (DEBUG_EXCEPTIONS) |
|
2220 |
if (loglevel != 0) { |
|
2221 |
fprintf(logfile, "ISI exception: msr=" ADDRX ", nip=" ADDRX "\n", |
|
2122 |
LOG_EXCP("ISI exception: msr=" ADDRX ", nip=" ADDRX "\n", |
|
2222 | 2123 |
msr, env->nip); |
2223 |
} |
|
2224 |
#endif |
|
2225 | 2124 |
new_msr &= ~((target_ulong)1 << MSR_RI); |
2226 | 2125 |
if (lpes1 == 0) |
2227 | 2126 |
new_msr |= (target_ulong)MSR_HVB; |
... | ... | |
2244 | 2143 |
switch (env->error_code & ~0xF) { |
2245 | 2144 |
case POWERPC_EXCP_FP: |
2246 | 2145 |
if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) { |
2247 |
#if defined (DEBUG_EXCEPTIONS) |
|
2248 |
if (loglevel != 0) { |
|
2249 |
fprintf(logfile, "Ignore floating point exception\n"); |
|
2250 |
} |
|
2251 |
#endif |
|
2146 |
LOG_EXCP("Ignore floating point exception\n"); |
|
2252 | 2147 |
env->exception_index = POWERPC_EXCP_NONE; |
2253 | 2148 |
env->error_code = 0; |
2254 | 2149 |
return; |
... | ... | |
2262 | 2157 |
msr |= 0x00010000; |
2263 | 2158 |
break; |
2264 | 2159 |
case POWERPC_EXCP_INVAL: |
2265 |
#if defined (DEBUG_EXCEPTIONS) |
|
2266 |
if (loglevel != 0) { |
|
2267 |
fprintf(logfile, "Invalid instruction at " ADDRX "\n", |
|
2160 |
LOG_EXCP("Invalid instruction at " ADDRX "\n", |
|
2268 | 2161 |
env->nip); |
2269 |
} |
|
2270 |
#endif |
|
2271 | 2162 |
new_msr &= ~((target_ulong)1 << MSR_RI); |
2272 | 2163 |
if (lpes1 == 0) |
2273 | 2164 |
new_msr |= (target_ulong)MSR_HVB; |
... | ... | |
2327 | 2218 |
goto store_next; |
2328 | 2219 |
case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ |
2329 | 2220 |
/* FIT on 4xx */ |
2330 |
#if defined (DEBUG_EXCEPTIONS) |
|
2331 |
if (loglevel != 0) |
|
2332 |
fprintf(logfile, "FIT exception\n"); |
|
2333 |
#endif |
|
2221 |
LOG_EXCP("FIT exception\n"); |
|
2334 | 2222 |
new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ |
2335 | 2223 |
goto store_next; |
2336 | 2224 |
case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ |
2337 |
#if defined (DEBUG_EXCEPTIONS) |
|
2338 |
if (loglevel != 0) |
|
2339 |
fprintf(logfile, "WDT exception\n"); |
|
2340 |
#endif |
|
2225 |
LOG_EXCP("WDT exception\n"); |
|
2341 | 2226 |
switch (excp_model) { |
2342 | 2227 |
case POWERPC_EXCP_BOOKE: |
2343 | 2228 |
srr0 = SPR_BOOKE_CSRR0; |
... | ... | |
2458 | 2343 |
new_msr |= (target_ulong)MSR_HVB; |
2459 | 2344 |
goto store_current; |
2460 | 2345 |
case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ |
2461 |
#if defined (DEBUG_EXCEPTIONS) |
|
2462 |
if (loglevel != 0) |
|
2463 |
fprintf(logfile, "PIT exception\n"); |
|
2464 |
#endif |
|
2346 |
LOG_EXCP("PIT exception\n"); |
|
2465 | 2347 |
new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ |
2466 | 2348 |
goto store_next; |
2467 | 2349 |
case POWERPC_EXCP_IO: /* IO error exception */ |
Also available in: Unified diff