Revision daf4f96e

b/target-ppc/cpu.h
656 656
void store_booke_tcr (CPUPPCState *env, target_ulong val);
657 657
void store_booke_tsr (CPUPPCState *env, target_ulong val);
658 658
void ppc_tlb_invalidate_all (CPUPPCState *env);
659
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
660
#if defined(TARGET_PPC64)
661
void ppc_slb_invalidate_all (CPUPPCState *env);
662
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0);
663
#endif
659 664
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid);
660 665
#endif
661 666
#endif
b/target-ppc/exec.h
100 100
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong vaddr,
101 101
                          int rw, int access_type, int check_BATs);
102 102

  
103
void ppc6xx_tlb_invalidate_all (CPUState *env);
104
void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
105
                                 int is_code);
106 103
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
107 104
                       target_ulong pte0, target_ulong pte1);
108
void ppc4xx_tlb_invalidate_all (CPUState *env);
109
void ppc4xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
110
                                 uint32_t pid);
111 105

  
112 106
static inline void env_to_regs (void)
113 107
{
b/target-ppc/helper.c
237 237
    return nr;
238 238
}
239 239

  
240
void ppc6xx_tlb_invalidate_all (CPUState *env)
240
static void ppc6xx_tlb_invalidate_all (CPUState *env)
241 241
{
242 242
    ppc6xx_tlb_t *tlb;
243 243
    int nr, max;
......
253 253
        max *= 2;
254 254
    for (nr = 0; nr < max; nr++) {
255 255
        tlb = &env->tlb[nr].tlb6;
256
#if !defined(FLUSH_ALL_TLBS)
257
        tlb_flush_page(env, tlb->EPN);
258
#endif
259 256
        pte_invalidate(&tlb->pte0);
260 257
    }
261
#if defined(FLUSH_ALL_TLBS)
262 258
    tlb_flush(env, 1);
263
#endif
264 259
}
265 260

  
266 261
static inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
......
292 287
#endif
293 288
}
294 289

  
295
void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
296
                                 int is_code)
290
static void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
291
                                        int is_code)
297 292
{
298 293
    __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
299 294
}
......
834 829
        return -1;
835 830
    }
836 831
    mask = ~(tlb->size - 1);
832
#if defined (DEBUG_SOFTWARE_TLB)
837 833
    if (loglevel != 0) {
838 834
        fprintf(logfile, "%s: TLB %d address " ADDRX " PID %d <=> "
839 835
                ADDRX " " ADDRX " %d\n",
840 836
                __func__, i, address, pid, tlb->EPN, mask, (int)tlb->PID);
841 837
    }
838
#endif
842 839
    /* Check PID */
843 840
    if (tlb->PID != 0 && tlb->PID != pid)
844 841
        return -1;
......
876 873
    return ret;
877 874
}
878 875

  
879
void ppc4xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
880
                                 uint32_t pid)
876
/* Helpers specific to PowerPC 40x implementations */
877
static void ppc4xx_tlb_invalidate_all (CPUState *env)
881 878
{
882 879
    ppcemb_tlb_t *tlb;
883
    target_phys_addr_t raddr;
884
    target_ulong page, end;
885 880
    int i;
886 881

  
887 882
    for (i = 0; i < env->nb_tlb; i++) {
888 883
        tlb = &env->tlb[i].tlbe;
889
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
890
            end = tlb->EPN + tlb->size;
891
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
892
                tlb_flush_page(env, page);
893
            tlb->prot &= ~PAGE_VALID;
894
            break;
895
        }
884
        tlb->prot &= ~PAGE_VALID;
896 885
    }
886
    tlb_flush(env, 1);
897 887
}
898 888

  
899
/* Helpers specific to PowerPC 40x implementations */
900
void ppc4xx_tlb_invalidate_all (CPUState *env)
889
static void ppc4xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
890
                                        uint32_t pid)
901 891
{
892
#if !defined(FLUSH_ALL_TLBS)
902 893
    ppcemb_tlb_t *tlb;
894
    target_phys_addr_t raddr;
895
    target_ulong page, end;
903 896
    int i;
904 897

  
905 898
    for (i = 0; i < env->nb_tlb; i++) {
906 899
        tlb = &env->tlb[i].tlbe;
907
        if (tlb->prot & PAGE_VALID) {
908
#if 0 // XXX: TLB have variable sizes then we flush all Qemu TLB.
900
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
909 901
            end = tlb->EPN + tlb->size;
910 902
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
911 903
                tlb_flush_page(env, page);
912
#endif
913 904
            tlb->prot &= ~PAGE_VALID;
905
            break;
914 906
        }
915 907
    }
916
    tlb_flush(env, 1);
908
#else
909
    ppc4xx_tlb_invalidate_all(env);
910
#endif
917 911
}
918 912

  
919 913
int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
......
932 926
            continue;
933 927
        zsel = (tlb->attr >> 4) & 0xF;
934 928
        zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
929
#if defined (DEBUG_SOFTWARE_TLB)
935 930
        if (loglevel != 0) {
936 931
            fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
937 932
                    __func__, i, zsel, zpr, rw, tlb->attr);
938 933
        }
934
#endif
939 935
        if (access_type == ACCESS_CODE) {
940 936
            /* Check execute enable bit */
941 937
            switch (zpr) {
......
1009 1005
        }
1010 1006
        if (ret >= 0) {
1011 1007
            ctx->raddr = raddr;
1008
#if defined (DEBUG_SOFTWARE_TLB)
1012 1009
            if (loglevel != 0) {
1013 1010
                fprintf(logfile, "%s: access granted " ADDRX " => " REGX
1014 1011
                        " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1015 1012
                        ret);
1016 1013
            }
1014
#endif
1017 1015
            return 0;
1018 1016
        }
1019 1017
    }
1018
#if defined (DEBUG_SOFTWARE_TLB)
1020 1019
    if (loglevel != 0) {
1021 1020
        fprintf(logfile, "%s: access refused " ADDRX " => " REGX
1022 1021
                " %d %d\n", __func__, address, raddr, ctx->prot,
1023 1022
                ret);
1024 1023
    }
1024
#endif
1025 1025

  
1026 1026
    return ret;
1027 1027
}
......
1569 1569
/* TLB management */
1570 1570
void ppc_tlb_invalidate_all (CPUPPCState *env)
1571 1571
{
1572
    if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) {
1572
    switch (env->mmu_model) {
1573
    case POWERPC_MMU_SOFT_6xx:
1573 1574
        ppc6xx_tlb_invalidate_all(env);
1574
    } else if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_4xx)) {
1575
        break;
1576
    case POWERPC_MMU_SOFT_4xx:
1577
    case POWERPC_MMU_SOFT_4xx_Z:
1575 1578
        ppc4xx_tlb_invalidate_all(env);
1576
    } else {
1579
        break;
1580
    default:
1577 1581
        tlb_flush(env, 1);
1582
        break;
1583
    }
1584
}
1585

  
1586
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1587
{
1588
#if !defined(FLUSH_ALL_TLBS)
1589
    addr &= TARGET_PAGE_MASK;
1590
    switch (env->mmu_model) {
1591
    case POWERPC_MMU_SOFT_6xx:
1592
        ppc6xx_tlb_invalidate_virt(env, addr, 0);
1593
        if (env->id_tlbs == 1)
1594
            ppc6xx_tlb_invalidate_virt(env, addr, 1);
1595
        break;
1596
    case POWERPC_MMU_SOFT_4xx:
1597
    case POWERPC_MMU_SOFT_4xx_Z:
1598
        ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
1599
        break;
1600
    default:
1601
        /* tlbie invalidate TLBs for all segments */
1602
        addr &= ~((target_ulong)-1 << 28);
1603
        /* XXX: this case should be optimized,
1604
         * giving a mask to tlb_flush_page
1605
         */
1606
        tlb_flush_page(env, addr | (0x0 << 28));
1607
        tlb_flush_page(env, addr | (0x1 << 28));
1608
        tlb_flush_page(env, addr | (0x2 << 28));
1609
        tlb_flush_page(env, addr | (0x3 << 28));
1610
        tlb_flush_page(env, addr | (0x4 << 28));
1611
        tlb_flush_page(env, addr | (0x5 << 28));
1612
        tlb_flush_page(env, addr | (0x6 << 28));
1613
        tlb_flush_page(env, addr | (0x7 << 28));
1614
        tlb_flush_page(env, addr | (0x8 << 28));
1615
        tlb_flush_page(env, addr | (0x9 << 28));
1616
        tlb_flush_page(env, addr | (0xA << 28));
1617
        tlb_flush_page(env, addr | (0xB << 28));
1618
        tlb_flush_page(env, addr | (0xC << 28));
1619
        tlb_flush_page(env, addr | (0xD << 28));
1620
        tlb_flush_page(env, addr | (0xE << 28));
1621
        tlb_flush_page(env, addr | (0xF << 28));
1578 1622
    }
1623
#else
1624
    ppc_tlb_invalidate_all(env);
1625
#endif
1579 1626
}
1580 1627

  
1628
#if defined(TARGET_PPC64)
1629
void ppc_slb_invalidate_all (CPUPPCState *env)
1630
{
1631
    /* XXX: TODO */
1632
    tlb_flush(env, 1);
1633
}
1634

  
1635
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
1636
{
1637
    /* XXX: TODO */
1638
    tlb_flush(env, 1);
1639
}
1640
#endif
1641

  
1642

  
1581 1643
/*****************************************************************************/
1582 1644
/* Special registers manipulation */
1583 1645
#if defined(TARGET_PPC64)
b/target-ppc/op.c
1985 1985
/* tlbia */
1986 1986
void OPPROTO op_tlbia (void)
1987 1987
{
1988
    do_tlbia();
1988
    ppc_tlb_invalidate_all(env);
1989 1989
    RETURN();
1990 1990
}
1991 1991

  
1992 1992
/* tlbie */
1993 1993
void OPPROTO op_tlbie (void)
1994 1994
{
1995
    do_tlbie();
1995
    ppc_tlb_invalidate_one(env, (uint32_t)T0);
1996 1996
    RETURN();
1997 1997
}
1998 1998

  
1999 1999
#if defined(TARGET_PPC64)
2000 2000
void OPPROTO op_tlbie_64 (void)
2001 2001
{
2002
    do_tlbie_64();
2002
    ppc_tlb_invalidate_one(env, T0);
2003 2003
    RETURN();
2004 2004
}
2005 2005
#endif
......
2007 2007
#if defined(TARGET_PPC64)
2008 2008
void OPPROTO op_slbia (void)
2009 2009
{
2010
    do_slbia();
2010
    ppc_slb_invalidate_all(env);
2011 2011
    RETURN();
2012 2012
}
2013 2013

  
2014 2014
void OPPROTO op_slbie (void)
2015 2015
{
2016
    do_slbie();
2016
    ppc_slb_invalidate_one(env, (uint32_t)T0);
2017
    RETURN();
2018
}
2019

  
2020
void OPPROTO op_slbie_64 (void)
2021
{
2022
    ppc_slb_invalidate_one(env, T0);
2017 2023
    RETURN();
2018 2024
}
2019 2025
#endif
......
2487 2493

  
2488 2494
void OPPROTO op_440_tlbsx (void)
2489 2495
{
2490
    do_440_tlbsx();
2496
    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
2491 2497
    RETURN();
2492 2498
}
2493 2499

  
2494
void OPPROTO op_440_tlbsx_ (void)
2500
void OPPROTO op_4xx_tlbsx_check (void)
2495 2501
{
2496
    do_440_tlbsx_();
2502
    int tmp;
2503

  
2504
    tmp = xer_so;
2505
    if (T0 != -1)
2506
        tmp |= 0x02;
2507
    env->crf[0] = tmp;
2497 2508
    RETURN();
2498 2509
}
2499 2510

  
......
2517 2528

  
2518 2529
void OPPROTO op_4xx_tlbsx (void)
2519 2530
{
2520
    do_4xx_tlbsx();
2521
    RETURN();
2522
}
2523

  
2524
void OPPROTO op_4xx_tlbsx_ (void)
2525
{
2526
    do_4xx_tlbsx_();
2531
    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
2527 2532
    RETURN();
2528 2533
}
2529 2534

  
b/target-ppc/op_helper.c
36 36
//#define DEBUG_OP
37 37
//#define DEBUG_EXCEPTIONS
38 38
//#define DEBUG_SOFTWARE_TLB
39
//#define FLUSH_ALL_TLBS
40 39

  
41 40
/*****************************************************************************/
42 41
/* Exceptions processing helpers */
......
2336 2335
    env = saved_env;
2337 2336
}
2338 2337

  
2339
/* TLB invalidation helpers */
2340
void do_tlbia (void)
2341
{
2342
    ppc_tlb_invalidate_all(env);
2343
}
2344

  
2345
void do_tlbie (void)
2346
{
2347
    T0 = (uint32_t)T0;
2348
#if !defined(FLUSH_ALL_TLBS)
2349
    /* XXX: Remove thoses tests */
2350
    if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) {
2351
        ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 0);
2352
        if (env->id_tlbs == 1)
2353
            ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 1);
2354
    } else if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_4xx)) {
2355
        ppc4xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK,
2356
                                   env->spr[SPR_40x_PID]);
2357
    } else {
2358
        /* tlbie invalidate TLBs for all segments */
2359
        T0 &= TARGET_PAGE_MASK;
2360
        T0 &= ~((target_ulong)-1 << 28);
2361
        /* XXX: this case should be optimized,
2362
         * giving a mask to tlb_flush_page
2363
         */
2364
        tlb_flush_page(env, T0 | (0x0 << 28));
2365
        tlb_flush_page(env, T0 | (0x1 << 28));
2366
        tlb_flush_page(env, T0 | (0x2 << 28));
2367
        tlb_flush_page(env, T0 | (0x3 << 28));
2368
        tlb_flush_page(env, T0 | (0x4 << 28));
2369
        tlb_flush_page(env, T0 | (0x5 << 28));
2370
        tlb_flush_page(env, T0 | (0x6 << 28));
2371
        tlb_flush_page(env, T0 | (0x7 << 28));
2372
        tlb_flush_page(env, T0 | (0x8 << 28));
2373
        tlb_flush_page(env, T0 | (0x9 << 28));
2374
        tlb_flush_page(env, T0 | (0xA << 28));
2375
        tlb_flush_page(env, T0 | (0xB << 28));
2376
        tlb_flush_page(env, T0 | (0xC << 28));
2377
        tlb_flush_page(env, T0 | (0xD << 28));
2378
        tlb_flush_page(env, T0 | (0xE << 28));
2379
        tlb_flush_page(env, T0 | (0xF << 28));
2380
    }
2381
#else
2382
    do_tlbia();
2383
#endif
2384
}
2385

  
2386
#if defined(TARGET_PPC64)
2387
void do_tlbie_64 (void)
2388
{
2389
    T0 = (uint64_t)T0;
2390
#if !defined(FLUSH_ALL_TLBS)
2391
    if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) {
2392
        ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 0);
2393
        if (env->id_tlbs == 1)
2394
            ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 1);
2395
    } else if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_4xx)) {
2396
        /* XXX: TODO */
2397
#if 0
2398
        ppcbooke_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK,
2399
                                     env->spr[SPR_BOOKE_PID]);
2400
#endif
2401
    } else {
2402
        /* tlbie invalidate TLBs for all segments
2403
         * As we have 2^36 segments, invalidate all qemu TLBs
2404
         */
2405
#if 0
2406
        T0 &= TARGET_PAGE_MASK;
2407
        T0 &= ~((target_ulong)-1 << 28);
2408
        /* XXX: this case should be optimized,
2409
         * giving a mask to tlb_flush_page
2410
         */
2411
        tlb_flush_page(env, T0 | (0x0 << 28));
2412
        tlb_flush_page(env, T0 | (0x1 << 28));
2413
        tlb_flush_page(env, T0 | (0x2 << 28));
2414
        tlb_flush_page(env, T0 | (0x3 << 28));
2415
        tlb_flush_page(env, T0 | (0x4 << 28));
2416
        tlb_flush_page(env, T0 | (0x5 << 28));
2417
        tlb_flush_page(env, T0 | (0x6 << 28));
2418
        tlb_flush_page(env, T0 | (0x7 << 28));
2419
        tlb_flush_page(env, T0 | (0x8 << 28));
2420
        tlb_flush_page(env, T0 | (0x9 << 28));
2421
        tlb_flush_page(env, T0 | (0xA << 28));
2422
        tlb_flush_page(env, T0 | (0xB << 28));
2423
        tlb_flush_page(env, T0 | (0xC << 28));
2424
        tlb_flush_page(env, T0 | (0xD << 28));
2425
        tlb_flush_page(env, T0 | (0xE << 28));
2426
        tlb_flush_page(env, T0 | (0xF << 28));
2427
#else
2428
        tlb_flush(env, 1);
2429
#endif
2430
    }
2431
#else
2432
    do_tlbia();
2433
#endif
2434
}
2435
#endif
2436

  
2437
#if defined(TARGET_PPC64)
2438
void do_slbia (void)
2439
{
2440
    /* XXX: TODO */
2441
    tlb_flush(env, 1);
2442
}
2443

  
2444
void do_slbie (void)
2445
{
2446
    /* XXX: TODO */
2447
    tlb_flush(env, 1);
2448
}
2449
#endif
2450

  
2451 2338
/* Software driven TLBs management */
2452 2339
/* PowerPC 602/603 software TLB load instructions helpers */
2453 2340
void do_load_6xx_tlb (int is_code)
......
2575 2462
        T0 |= 0x100;
2576 2463
}
2577 2464

  
2578
void do_4xx_tlbsx (void)
2579
{
2580
    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
2581
}
2582

  
2583
void do_4xx_tlbsx_ (void)
2584
{
2585
    int tmp = xer_so;
2586

  
2587
    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]);
2588
    if (T0 != -1)
2589
        tmp |= 0x02;
2590
    env->crf[0] = tmp;
2591
}
2592

  
2593 2465
void do_4xx_tlbwe_hi (void)
2594 2466
{
2595 2467
    ppcemb_tlb_t *tlb;
......
2757 2629
    }
2758 2630
}
2759 2631

  
2760
void do_440_tlbsx (void)
2761
{
2762
    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
2763
}
2764

  
2765
void do_440_tlbsx_ (void)
2766
{
2767
    int tmp = xer_so;
2768

  
2769
    T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
2770
    if (T0 != -1)
2771
        tmp |= 0x02;
2772
    env->crf[0] = tmp;
2773
}
2774

  
2775 2632
void do_440_tlbre (int word)
2776 2633
{
2777 2634
    ppcemb_tlb_t *tlb;
b/target-ppc/translate.c
4991 4991
        return;
4992 4992
    }
4993 4993
    gen_addr_reg_index(ctx);
4994
    gen_op_4xx_tlbsx();
4994 4995
    if (Rc(ctx->opcode))
4995
        gen_op_4xx_tlbsx_();
4996
    else
4997
        gen_op_4xx_tlbsx();
4996
        gen_op_4xx_tlbsx_check();
4998 4997
    gen_op_store_T0_gpr(rD(ctx->opcode));
4999 4998
#endif
5000 4999
}
......
5064 5063
        return;
5065 5064
    }
5066 5065
    gen_addr_reg_index(ctx);
5066
    gen_op_440_tlbsx();
5067 5067
    if (Rc(ctx->opcode))
5068
        gen_op_440_tlbsx_();
5069
    else
5070
        gen_op_440_tlbsx();
5068
        gen_op_4xx_tlbsx_check();
5071 5069
    gen_op_store_T0_gpr(rD(ctx->opcode));
5072 5070
#endif
5073 5071
}

Also available in: Unified diff