Revision d720b93d

b/cpu-all.h
681 681
#define IO_MEM_CODE        (3 << IO_MEM_SHIFT) /* used internally, never use directly */
682 682
#define IO_MEM_NOTDIRTY    (4 << IO_MEM_SHIFT) /* used internally, never use directly */
683 683

  
684
/* NOTE: vaddr is only used internally. Never use it except if you know what you do */
685
typedef void CPUWriteMemoryFunc(uint32_t addr, uint32_t value, uint32_t vaddr);
684
typedef void CPUWriteMemoryFunc(uint32_t addr, uint32_t value);
686 685
typedef uint32_t CPUReadMemoryFunc(uint32_t addr);
687 686

  
688 687
void cpu_register_physical_memory(unsigned long start_addr, unsigned long size,
b/exec.c
168 168

  
169 169
#if !defined(CONFIG_USER_ONLY)
170 170
static void tlb_protect_code(CPUState *env, uint32_t addr);
171
static void tlb_unprotect_code(CPUState *env, uint32_t addr);
172 171
static void tlb_unprotect_code_phys(CPUState *env, uint32_t phys_addr, target_ulong vaddr);
173 172

  
174 173
static inline VirtPageDesc *virt_page_find_alloc(unsigned int index)
......
533 532
    }
534 533
}
535 534

  
535
#ifdef TARGET_HAS_PRECISE_SMC
536

  
537
static void tb_gen_code(CPUState *env, 
538
                        target_ulong pc, target_ulong cs_base, int flags,
539
                        int cflags)
540
{
541
    TranslationBlock *tb;
542
    uint8_t *tc_ptr;
543
    target_ulong phys_pc, phys_page2, virt_page2;
544
    int code_gen_size;
545

  
546
    phys_pc = get_phys_addr_code(env, (unsigned long)pc);
547
    tb = tb_alloc((unsigned long)pc);
548
    if (!tb) {
549
        /* flush must be done */
550
        tb_flush(env);
551
        /* cannot fail at this point */
552
        tb = tb_alloc((unsigned long)pc);
553
    }
554
    tc_ptr = code_gen_ptr;
555
    tb->tc_ptr = tc_ptr;
556
    tb->cs_base = cs_base;
557
    tb->flags = flags;
558
    tb->cflags = cflags;
559
    cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
560
    code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
561
    
562
    /* check next page if needed */
563
    virt_page2 = ((unsigned long)pc + tb->size - 1) & TARGET_PAGE_MASK;
564
    phys_page2 = -1;
565
    if (((unsigned long)pc & TARGET_PAGE_MASK) != virt_page2) {
566
        phys_page2 = get_phys_addr_code(env, virt_page2);
567
    }
568
    tb_link_phys(tb, phys_pc, phys_page2);
569
}
570
#endif
571
    
536 572
/* invalidate all TBs which intersect with the target physical page
537 573
   starting in range [start;end[. NOTE: start and end must refer to
538
   the same physical page. 'vaddr' is a virtual address referencing
539
   the physical page of code. It is only used an a hint if there is no
540
   code left. */
541
static void tb_invalidate_phys_page_range(target_ulong start, target_ulong end, 
542
                                          target_ulong vaddr)
543
{
544
    int n;
574
   the same physical page. 'is_cpu_write_access' should be true if called
575
   from a real cpu write access: the virtual CPU will exit the current
576
   TB if code is modified inside this TB. */
577
void tb_invalidate_phys_page_range(target_ulong start, target_ulong end, 
578
                                   int is_cpu_write_access)
579
{
580
    int n, current_tb_modified, current_tb_not_found, current_flags;
581
#if defined(TARGET_HAS_PRECISE_SMC) || !defined(CONFIG_USER_ONLY)
582
    CPUState *env = cpu_single_env;
583
#endif
545 584
    PageDesc *p;
546
    TranslationBlock *tb, *tb_next;
585
    TranslationBlock *tb, *tb_next, *current_tb;
547 586
    target_ulong tb_start, tb_end;
587
    target_ulong current_pc, current_cs_base;
548 588

  
549 589
    p = page_find(start >> TARGET_PAGE_BITS);
550 590
    if (!p) 
551 591
        return;
552 592
    if (!p->code_bitmap && 
553
        ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD) {
593
        ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
594
        is_cpu_write_access) {
554 595
        /* build code bitmap */
555 596
        build_page_bitmap(p);
556 597
    }
557 598

  
558 599
    /* we remove all the TBs in the range [start, end[ */
559 600
    /* XXX: see if in some cases it could be faster to invalidate all the code */
601
    current_tb_not_found = is_cpu_write_access;
602
    current_tb_modified = 0;
603
    current_tb = NULL; /* avoid warning */
604
    current_pc = 0; /* avoid warning */
605
    current_cs_base = 0; /* avoid warning */
606
    current_flags = 0; /* avoid warning */
560 607
    tb = p->first_tb;
561 608
    while (tb != NULL) {
562 609
        n = (long)tb & 3;
......
573 620
            tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
574 621
        }
575 622
        if (!(tb_end <= start || tb_start >= end)) {
623
#ifdef TARGET_HAS_PRECISE_SMC
624
            if (current_tb_not_found) {
625
                current_tb_not_found = 0;
626
                current_tb = NULL;
627
                if (env->mem_write_pc) {
628
                    /* now we have a real cpu fault */
629
                    current_tb = tb_find_pc(env->mem_write_pc);
630
                }
631
            }
632
            if (current_tb == tb &&
633
                !(current_tb->cflags & CF_SINGLE_INSN)) {
634
                /* If we are modifying the current TB, we must stop
635
                its execution. We could be more precise by checking
636
                that the modification is after the current PC, but it
637
                would require a specialized function to partially
638
                restore the CPU state */
639
                
640
                current_tb_modified = 1;
641
                cpu_restore_state(current_tb, env, 
642
                                  env->mem_write_pc, NULL);
643
#if defined(TARGET_I386)
644
                current_flags = env->hflags;
645
                current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
646
                current_cs_base = (target_ulong)env->segs[R_CS].base;
647
                current_pc = current_cs_base + env->eip;
648
#else
649
#error unsupported CPU
650
#endif
651
            }
652
#endif /* TARGET_HAS_PRECISE_SMC */
576 653
            tb_phys_invalidate(tb, -1);
577 654
        }
578 655
        tb = tb_next;
......
581 658
    /* if no code remaining, no need to continue to use slow writes */
582 659
    if (!p->first_tb) {
583 660
        invalidate_page_bitmap(p);
584
        tlb_unprotect_code_phys(cpu_single_env, start, vaddr);
661
        if (is_cpu_write_access) {
662
            tlb_unprotect_code_phys(env, start, env->mem_write_vaddr);
663
        }
664
    }
665
#endif
666
#ifdef TARGET_HAS_PRECISE_SMC
667
    if (current_tb_modified) {
668
        /* we generate a block containing just the instruction
669
           modifying the memory. It will ensure that it cannot modify
670
           itself */
671
        tb_gen_code(env, current_pc, current_cs_base, current_flags, 
672
                    CF_SINGLE_INSN);
673
        cpu_resume_from_signal(env, NULL);
585 674
    }
586 675
#endif
587 676
}
588 677

  
589 678
/* len must be <= 8 and start must be a multiple of len */
590
static inline void tb_invalidate_phys_page_fast(target_ulong start, int len, target_ulong vaddr)
679
static inline void tb_invalidate_phys_page_fast(target_ulong start, int len)
591 680
{
592 681
    PageDesc *p;
593 682
    int offset, b;
......
608 697
            goto do_invalidate;
609 698
    } else {
610 699
    do_invalidate:
611
        tb_invalidate_phys_page_range(start, start + len, vaddr);
700
        tb_invalidate_phys_page_range(start, start + len, 1);
612 701
    }
613 702
}
614 703

  
615
/* invalidate all TBs which intersect with the target virtual page
616
   starting in range [start;end[. This function is usually used when
617
   the target processor flushes its I-cache. NOTE: start and end must
618
   refer to the same physical page */
619
void tb_invalidate_page_range(target_ulong start, target_ulong end)
620
{
621
    int n;
622
    PageDesc *p;
623
    TranslationBlock *tb, *tb_next;
624
    target_ulong pc;
625
    target_ulong phys_start;
626

  
627
#if !defined(CONFIG_USER_ONLY)
628
    {
629
        VirtPageDesc *vp;
630
        vp = virt_page_find(start >> TARGET_PAGE_BITS);
631
        if (!vp)
632
            return;
633
        if (vp->valid_tag != virt_valid_tag)
634
            return;
635
        phys_start = vp->phys_addr + (start & ~TARGET_PAGE_MASK);
636
    }
637
#else
638
    phys_start = start;
639
#endif    
640
    p = page_find(phys_start >> TARGET_PAGE_BITS);
641
    if (!p) 
642
        return;
643
    /* we remove all the TBs in the range [start, end[ */
644
    /* XXX: see if in some cases it could be faster to invalidate all the code */
645
    tb = p->first_tb;
646
    while (tb != NULL) {
647
        n = (long)tb & 3;
648
        tb = (TranslationBlock *)((long)tb & ~3);
649
        tb_next = tb->page_next[n];
650
        pc = tb->pc;
651
        if (!((pc + tb->size) <= start || pc >= end)) {
652
            tb_phys_invalidate(tb, -1);
653
        }
654
        tb = tb_next;
655
    }
656
#if !defined(CONFIG_USER_ONLY)
657
    /* if no code remaining, no need to continue to use slow writes */
658
    if (!p->first_tb)
659
        tlb_unprotect_code(cpu_single_env, start);
660
#endif
661
}
662

  
663 704
#if !defined(CONFIG_SOFTMMU)
664
static void tb_invalidate_phys_page(target_ulong addr)
705
static void tb_invalidate_phys_page(target_ulong addr, 
706
                                    unsigned long pc, void *puc)
665 707
{
666
    int n;
708
    int n, current_flags, current_tb_modified;
709
    target_ulong current_pc, current_cs_base;
667 710
    PageDesc *p;
668
    TranslationBlock *tb;
711
    TranslationBlock *tb, *current_tb;
712
#ifdef TARGET_HAS_PRECISE_SMC
713
    CPUState *env = cpu_single_env;
714
#endif
669 715

  
670 716
    addr &= TARGET_PAGE_MASK;
671 717
    p = page_find(addr >> TARGET_PAGE_BITS);
672 718
    if (!p) 
673 719
        return;
674 720
    tb = p->first_tb;
721
    current_tb_modified = 0;
722
    current_tb = NULL;
723
    current_pc = 0; /* avoid warning */
724
    current_cs_base = 0; /* avoid warning */
725
    current_flags = 0; /* avoid warning */
726
#ifdef TARGET_HAS_PRECISE_SMC
727
    if (tb && pc != 0) {
728
        current_tb = tb_find_pc(pc);
729
    }
730
#endif
675 731
    while (tb != NULL) {
676 732
        n = (long)tb & 3;
677 733
        tb = (TranslationBlock *)((long)tb & ~3);
734
#ifdef TARGET_HAS_PRECISE_SMC
735
        if (current_tb == tb &&
736
            !(current_tb->cflags & CF_SINGLE_INSN)) {
737
                /* If we are modifying the current TB, we must stop
738
                   its execution. We could be more precise by checking
739
                   that the modification is after the current PC, but it
740
                   would require a specialized function to partially
741
                   restore the CPU state */
742
            
743
            current_tb_modified = 1;
744
            cpu_restore_state(current_tb, env, pc, puc);
745
#if defined(TARGET_I386)
746
            current_flags = env->hflags;
747
            current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
748
            current_cs_base = (target_ulong)env->segs[R_CS].base;
749
            current_pc = current_cs_base + env->eip;
750
#else
751
#error unsupported CPU
752
#endif
753
        }
754
#endif /* TARGET_HAS_PRECISE_SMC */
678 755
        tb_phys_invalidate(tb, addr);
679 756
        tb = tb->page_next[n];
680 757
    }
681 758
    p->first_tb = NULL;
759
#ifdef TARGET_HAS_PRECISE_SMC
760
    if (current_tb_modified) {
761
        /* we generate a block containing just the instruction
762
           modifying the memory. It will ensure that it cannot modify
763
           itself */
764
        tb_gen_code(env, current_pc, current_cs_base, current_flags, 
765
                    CF_SINGLE_INSN);
766
        cpu_resume_from_signal(env, puc);
767
    }
768
#endif
682 769
}
683 770
#endif
684 771

  
......
696 783
    p->first_tb = (TranslationBlock *)((long)tb | n);
697 784
    invalidate_page_bitmap(p);
698 785

  
786
#ifdef TARGET_HAS_SMC
787

  
699 788
#if defined(CONFIG_USER_ONLY)
700 789
    if (p->flags & PAGE_WRITE) {
701 790
        unsigned long host_start, host_end, addr;
......
727 816
        tlb_protect_code(cpu_single_env, virt_addr);        
728 817
    }
729 818
#endif
819

  
820
#endif /* TARGET_HAS_SMC */
730 821
}
731 822

  
732 823
/* Allocate a new translation block. Flush the translation buffer if
......
910 1001
    tb_reset_jump_recursive2(tb, 1);
911 1002
}
912 1003

  
1004
static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1005
{
1006
    target_ulong phys_addr;
1007

  
1008
    phys_addr = cpu_get_phys_page_debug(env, pc);
1009
    tb_invalidate_phys_page_range(phys_addr, phys_addr + 1, 0);
1010
}
1011

  
913 1012
/* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
914 1013
   breakpoint is reached */
915 1014
int cpu_breakpoint_insert(CPUState *env, uint32_t pc)
916 1015
{
917 1016
#if defined(TARGET_I386) || defined(TARGET_PPC)
918 1017
    int i;
919

  
1018
    
920 1019
    for(i = 0; i < env->nb_breakpoints; i++) {
921 1020
        if (env->breakpoints[i] == pc)
922 1021
            return 0;
......
925 1024
    if (env->nb_breakpoints >= MAX_BREAKPOINTS)
926 1025
        return -1;
927 1026
    env->breakpoints[env->nb_breakpoints++] = pc;
928
    tb_invalidate_page_range(pc, pc + 1);
1027
    
1028
    breakpoint_invalidate(env, pc);
929 1029
    return 0;
930 1030
#else
931 1031
    return -1;
......
946 1046
    memmove(&env->breakpoints[i], &env->breakpoints[i + 1],
947 1047
            (env->nb_breakpoints - (i + 1)) * sizeof(env->breakpoints[0]));
948 1048
    env->nb_breakpoints--;
949
    tb_invalidate_page_range(pc, pc + 1);
1049

  
1050
    breakpoint_invalidate(env, pc);
950 1051
    return 0;
951 1052
#else
952 1053
    return -1;
......
1197 1298
#endif
1198 1299
}
1199 1300

  
1200
static inline void tlb_unprotect_code1(CPUTLBEntry *tlb_entry, uint32_t addr)
1201
{
1202
    if (addr == (tlb_entry->address & 
1203
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) &&
1204
        (tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_CODE) {
1205
        tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
1206
    }
1207
}
1208

  
1209
/* update the TLB so that writes in virtual page 'addr' are no longer
1210
   tested self modifying code */
1211
static void tlb_unprotect_code(CPUState *env, uint32_t addr)
1212
{
1213
    int i;
1214

  
1215
    addr &= TARGET_PAGE_MASK;
1216
    i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1217
    tlb_unprotect_code1(&env->tlb_write[0][i], addr);
1218
    tlb_unprotect_code1(&env->tlb_write[1][i], addr);
1219
}
1220

  
1221 1301
static inline void tlb_unprotect_code2(CPUTLBEntry *tlb_entry, 
1222 1302
                                       uint32_t phys_addr)
1223 1303
{
......
1387 1467
                /* ROM: access is ignored (same as unassigned) */
1388 1468
                env->tlb_write[is_user][index].address = vaddr | IO_MEM_ROM;
1389 1469
                env->tlb_write[is_user][index].addend = addend;
1390
            } else if (first_tb) {
1470
            } else 
1471
                /* XXX: the PowerPC code seems not ready to handle
1472
                   self modifying code with DCBI */
1473
#if defined(TARGET_HAS_SMC) || 1
1474
            if (first_tb) {
1391 1475
                /* if code is present, we use a specific memory
1392 1476
                   handler. It works only for physical memory access */
1393 1477
                env->tlb_write[is_user][index].address = vaddr | IO_MEM_CODE;
1394 1478
                env->tlb_write[is_user][index].addend = addend;
1395
            } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
1479
            } else 
1480
#endif
1481
            if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
1396 1482
                       !cpu_physical_memory_is_dirty(pd)) {
1397 1483
                env->tlb_write[is_user][index].address = vaddr | IO_MEM_NOTDIRTY;
1398 1484
                env->tlb_write[is_user][index].addend = addend;
......
1420 1506
            } else {
1421 1507
                if (prot & PROT_WRITE) {
1422 1508
                    if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM || 
1509
#if defined(TARGET_HAS_SMC) || 1
1423 1510
                        first_tb ||
1511
#endif
1424 1512
                        ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
1425 1513
                         !cpu_physical_memory_is_dirty(pd))) {
1426 1514
                        /* ROM: we do as if code was inside */
......
1450 1538

  
1451 1539
/* called from signal handler: invalidate the code and unprotect the
1452 1540
   page. Return TRUE if the fault was succesfully handled. */
1453
int page_unprotect(unsigned long addr)
1541
int page_unprotect(unsigned long addr, unsigned long pc, void *puc)
1454 1542
{
1455 1543
#if !defined(CONFIG_SOFTMMU)
1456 1544
    VirtPageDesc *vp;
......
1476 1564
    printf("page_unprotect: addr=0x%08x phys_addr=0x%08x prot=%x\n", 
1477 1565
           addr, vp->phys_addr, vp->prot);
1478 1566
#endif
1479
    /* set the dirty bit */
1480
    phys_ram_dirty[vp->phys_addr >> TARGET_PAGE_BITS] = 1;
1481
    /* flush the code inside */
1482
    tb_invalidate_phys_page(vp->phys_addr);
1483 1567
    if (mprotect((void *)addr, TARGET_PAGE_SIZE, vp->prot) < 0)
1484 1568
        cpu_abort(cpu_single_env, "error mprotect addr=0x%lx prot=%d\n",
1485 1569
                  (unsigned long)addr, vp->prot);
1570
    /* set the dirty bit */
1571
    phys_ram_dirty[vp->phys_addr >> TARGET_PAGE_BITS] = 1;
1572
    /* flush the code inside */
1573
    tb_invalidate_phys_page(vp->phys_addr, pc, puc);
1486 1574
    return 1;
1487 1575
#else
1488 1576
    return 0;
......
1582 1670
        if (!(p->flags & PAGE_WRITE) && 
1583 1671
            (flags & PAGE_WRITE) &&
1584 1672
            p->first_tb) {
1585
            tb_invalidate_phys_page(addr);
1673
            tb_invalidate_phys_page(addr, 0, NULL);
1586 1674
        }
1587 1675
        p->flags = flags;
1588 1676
    }
......
1591 1679

  
1592 1680
/* called from signal handler: invalidate the code and unprotect the
1593 1681
   page. Return TRUE if the fault was succesfully handled. */
1594
int page_unprotect(unsigned long address)
1682
int page_unprotect(unsigned long address, unsigned long pc, void *puc)
1595 1683
{
1596 1684
    unsigned int page_index, prot, pindex;
1597 1685
    PageDesc *p, *p1;
......
1619 1707
            p1[pindex].flags |= PAGE_WRITE;
1620 1708
            /* and since the content will be modified, we must invalidate
1621 1709
               the corresponding translated code. */
1622
            tb_invalidate_phys_page(address);
1710
            tb_invalidate_phys_page(address, pc, puc);
1623 1711
#ifdef DEBUG_TB_CHECK
1624 1712
            tb_invalidate_check(address);
1625 1713
#endif
......
1639 1727
    start &= TARGET_PAGE_MASK;
1640 1728
    end = TARGET_PAGE_ALIGN(end);
1641 1729
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1642
        page_unprotect(addr);
1730
        page_unprotect(addr, 0, NULL);
1643 1731
    }
1644 1732
}
1645 1733

  
1646 1734
static inline void tlb_set_dirty(unsigned long addr, target_ulong vaddr)
1647 1735
{
1648 1736
}
1649

  
1650 1737
#endif /* defined(CONFIG_USER_ONLY) */
1651 1738

  
1652 1739
/* register physical memory. 'size' must be a multiple of the target
......
1672 1759
    return 0;
1673 1760
}
1674 1761

  
1675
static void unassigned_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
1762
static void unassigned_mem_writeb(uint32_t addr, uint32_t val)
1676 1763
{
1677 1764
}
1678 1765

  
......
1691 1778
/* self modifying code support in soft mmu mode : writing to a page
1692 1779
   containing code comes to these functions */
1693 1780

  
1694
static void code_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
1781
static void code_mem_writeb(uint32_t addr, uint32_t val)
1695 1782
{
1696 1783
    unsigned long phys_addr;
1697 1784

  
1698 1785
    phys_addr = addr - (long)phys_ram_base;
1699 1786
#if !defined(CONFIG_USER_ONLY)
1700
    tb_invalidate_phys_page_fast(phys_addr, 1, vaddr);
1787
    tb_invalidate_phys_page_fast(phys_addr, 1);
1701 1788
#endif
1702 1789
    stb_raw((uint8_t *)addr, val);
1703 1790
    phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 1;
1704 1791
}
1705 1792

  
1706
static void code_mem_writew(uint32_t addr, uint32_t val, uint32_t vaddr)
1793
static void code_mem_writew(uint32_t addr, uint32_t val)
1707 1794
{
1708 1795
    unsigned long phys_addr;
1709 1796

  
1710 1797
    phys_addr = addr - (long)phys_ram_base;
1711 1798
#if !defined(CONFIG_USER_ONLY)
1712
    tb_invalidate_phys_page_fast(phys_addr, 2, vaddr);
1799
    tb_invalidate_phys_page_fast(phys_addr, 2);
1713 1800
#endif
1714 1801
    stw_raw((uint8_t *)addr, val);
1715 1802
    phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 1;
1716 1803
}
1717 1804

  
1718
static void code_mem_writel(uint32_t addr, uint32_t val, uint32_t vaddr)
1805
static void code_mem_writel(uint32_t addr, uint32_t val)
1719 1806
{
1720 1807
    unsigned long phys_addr;
1721 1808

  
1722 1809
    phys_addr = addr - (long)phys_ram_base;
1723 1810
#if !defined(CONFIG_USER_ONLY)
1724
    tb_invalidate_phys_page_fast(phys_addr, 4, vaddr);
1811
    tb_invalidate_phys_page_fast(phys_addr, 4);
1725 1812
#endif
1726 1813
    stl_raw((uint8_t *)addr, val);
1727 1814
    phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 1;
......
1739 1826
    code_mem_writel,
1740 1827
};
1741 1828

  
1742
static void notdirty_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
1829
static void notdirty_mem_writeb(uint32_t addr, uint32_t val)
1743 1830
{
1744 1831
    stb_raw((uint8_t *)addr, val);
1745
    tlb_set_dirty(addr, vaddr);
1832
    tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
1746 1833
}
1747 1834

  
1748
static void notdirty_mem_writew(uint32_t addr, uint32_t val, uint32_t vaddr)
1835
static void notdirty_mem_writew(uint32_t addr, uint32_t val)
1749 1836
{
1750 1837
    stw_raw((uint8_t *)addr, val);
1751
    tlb_set_dirty(addr, vaddr);
1838
    tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
1752 1839
}
1753 1840

  
1754
static void notdirty_mem_writel(uint32_t addr, uint32_t val, uint32_t vaddr)
1841
static void notdirty_mem_writel(uint32_t addr, uint32_t val)
1755 1842
{
1756 1843
    stl_raw((uint8_t *)addr, val);
1757
    tlb_set_dirty(addr, vaddr);
1844
    tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
1758 1845
}
1759 1846

  
1760 1847
static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
......
1861 1948
                if (l >= 4 && ((addr & 3) == 0)) {
1862 1949
                    /* 32 bit read access */
1863 1950
                    val = ldl_raw(buf);
1864
                    io_mem_write[io_index][2](addr, val, 0);
1951
                    io_mem_write[io_index][2](addr, val);
1865 1952
                    l = 4;
1866 1953
                } else if (l >= 2 && ((addr & 1) == 0)) {
1867 1954
                    /* 16 bit read access */
1868 1955
                    val = lduw_raw(buf);
1869
                    io_mem_write[io_index][1](addr, val, 0);
1956
                    io_mem_write[io_index][1](addr, val);
1870 1957
                    l = 2;
1871 1958
                } else {
1872 1959
                    /* 8 bit access */
1873 1960
                    val = ldub_raw(buf);
1874
                    io_mem_write[io_index][0](addr, val, 0);
1961
                    io_mem_write[io_index][0](addr, val);
1875 1962
                    l = 1;
1876 1963
                }
1877 1964
            } else {
b/softmmu_template.h
70 70

  
71 71
static inline void glue(io_write, SUFFIX)(unsigned long physaddr, 
72 72
                                          DATA_TYPE val,
73
                                          unsigned long tlb_addr)
73
                                          unsigned long tlb_addr,
74
                                          void *retaddr)
74 75
{
75 76
    int index;
76 77

  
77 78
    index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
79
    env->mem_write_vaddr = tlb_addr;
80
    env->mem_write_pc = (unsigned long)retaddr;
78 81
#if SHIFT <= 2
79
    io_mem_write[index][SHIFT](physaddr, val, tlb_addr);
82
    io_mem_write[index][SHIFT](physaddr, val);
80 83
#else
81 84
#ifdef TARGET_WORDS_BIGENDIAN
82
    io_mem_write[index][2](physaddr, val >> 32, tlb_addr);
83
    io_mem_write[index][2](physaddr + 4, val, tlb_addr);
85
    io_mem_write[index][2](physaddr, val >> 32);
86
    io_mem_write[index][2](physaddr + 4, val);
84 87
#else
85
    io_mem_write[index][2](physaddr, val, tlb_addr);
86
    io_mem_write[index][2](physaddr + 4, val >> 32, tlb_addr);
88
    io_mem_write[index][2](physaddr, val);
89
    io_mem_write[index][2](physaddr + 4, val >> 32);
87 90
#endif
88 91
#endif /* SHIFT > 2 */
89 92
}
......
193 196
            /* IO access */
194 197
            if ((addr & (DATA_SIZE - 1)) != 0)
195 198
                goto do_unaligned_access;
196
            glue(io_write, SUFFIX)(physaddr, val, tlb_addr);
199
            retaddr = GETPC();
200
            glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr);
197 201
        } else if (((addr & 0xfff) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
198 202
        do_unaligned_access:
199 203
            retaddr = GETPC();
......
229 233
            /* IO access */
230 234
            if ((addr & (DATA_SIZE - 1)) != 0)
231 235
                goto do_unaligned_access;
232
            glue(io_write, SUFFIX)(physaddr, val, tlb_addr);
236
            glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr);
233 237
        } else if (((addr & 0xfff) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
234 238
        do_unaligned_access:
235 239
            /* XXX: not efficient, but simple */
b/target-arm/cpu.h
43 43
    struct TranslationBlock *current_tb;
44 44
    int user_mode_only;
45 45

  
46
    /* in order to avoid passing too many arguments to the memory
47
       write helpers, we store some rarely used information in the CPU
48
       context) */
49
    unsigned long mem_write_pc; /* host pc at which the memory was
50
                                   written */
51
    unsigned long mem_write_vaddr; /* target virtual addr at which the
52
                                      memory was written */
46 53
    /* user data */
47 54
    void *opaque;
48 55
} CPUARMState;
b/target-i386/cpu.h
22 22

  
23 23
#define TARGET_LONG_BITS 32
24 24

  
25
/* target supports implicit self modifying code */
26
#define TARGET_HAS_SMC
27
/* support for self modifying code even if the modified instruction is
28
   close to the modifying instruction */
29
#define TARGET_HAS_PRECISE_SMC
30

  
25 31
#include "cpu-defs.h"
26 32

  
27 33
#if defined(__i386__) && !defined(CONFIG_SOFTMMU)
......
331 337
    int interrupt_request; 
332 338
    int user_mode_only; /* user mode only simulation */
333 339

  
334
    /* soft mmu support */
335 340
    uint32_t a20_mask;
341

  
342
    /* soft mmu support */
343
    /* in order to avoid passing too many arguments to the memory
344
       write helpers, we store some rarely used information in the CPU
345
       context) */
346
    unsigned long mem_write_pc; /* host pc at which the memory was
347
                                   written */
348
    unsigned long mem_write_vaddr; /* target virtual addr at which the
349
                                      memory was written */
336 350
    /* 0 = kernel, 1 = user */
337 351
    CPUTLBEntry tlb_read[2][CPU_TLB_SIZE];
338 352
    CPUTLBEntry tlb_write[2][CPU_TLB_SIZE];
......
358 372
CPUX86State *cpu_x86_init(void);
359 373
int cpu_x86_exec(CPUX86State *s);
360 374
void cpu_x86_close(CPUX86State *s);
361
int cpu_x86_get_pic_interrupt(CPUX86State *s);
375
int cpu_get_pic_interrupt(CPUX86State *s);
362 376

  
363 377
/* this function must always be used to load data in the segment
364 378
   cache: it synchronizes the hflags with the segment cache values */
b/target-i386/translate-copy.c
1189 1189
        return -1;
1190 1190
    if (!(flags & HF_SS32_MASK))
1191 1191
        return -1;
1192
    if (tb->cflags & CF_SINGLE_INSN)
1193
        return -1;
1192 1194
    gen_code_end = gen_code_ptr + 
1193 1195
        GEN_CODE_MAX_SIZE - GEN_CODE_MAX_INSN_SIZE;
1194 1196
    dc->gen_code_ptr = gen_code_ptr;
b/target-i386/translate.c
4491 4491
    DisasContext dc1, *dc = &dc1;
4492 4492
    uint8_t *pc_ptr;
4493 4493
    uint16_t *gen_opc_end;
4494
    int flags, j, lj;
4494
    int flags, j, lj, cflags;
4495 4495
    uint8_t *pc_start;
4496 4496
    uint8_t *cs_base;
4497 4497
    
......
4499 4499
    pc_start = (uint8_t *)tb->pc;
4500 4500
    cs_base = (uint8_t *)tb->cs_base;
4501 4501
    flags = tb->flags;
4502
    cflags = tb->cflags;
4502 4503

  
4503 4504
    dc->pe = (flags >> HF_PE_SHIFT) & 1;
4504 4505
    dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
......
4573 4574
           the flag and abort the translation to give the irqs a
4574 4575
           change to be happen */
4575 4576
        if (dc->tf || dc->singlestep_enabled || 
4576
            (flags & HF_INHIBIT_IRQ_MASK)) {
4577
            (flags & HF_INHIBIT_IRQ_MASK) ||
4578
            (cflags & CF_SINGLE_INSN)) {
4577 4579
            gen_op_jmp_im(pc_ptr - dc->cs_base);
4578 4580
            gen_eob(dc);
4579 4581
            break;
b/target-ppc/cpu.h
164 164
    int user_mode_only; /* user mode only simulation */
165 165
    struct TranslationBlock *current_tb; /* currently executing TB */
166 166
    /* soft mmu support */
167
    /* in order to avoid passing too many arguments to the memory
168
       write helpers, we store some rarely used information in the CPU
169
       context) */
170
    unsigned long mem_write_pc; /* host pc at which the memory was
171
                                   written */
172
    unsigned long mem_write_vaddr; /* target virtual addr at which the
173
                                      memory was written */
167 174
    /* 0 = kernel, 1 = user (may have 2 = kernel code, 3 = user code ?) */
168 175
    CPUTLBEntry tlb_read[2][CPU_TLB_SIZE];
169 176
    CPUTLBEntry tlb_write[2][CPU_TLB_SIZE];
b/target-sparc/cpu.h
43 43
    void *opaque;
44 44
    /* NOTE: we allow 8 more registers to handle wrapping */
45 45
    uint32_t regbase[NWINDOWS * 16 + 8];
46

  
47
    /* in order to avoid passing too many arguments to the memory
48
       write helpers, we store some rarely used information in the CPU
49
       context) */
50
    unsigned long mem_write_pc; /* host pc at which the memory was
51
                                   written */
52
    unsigned long mem_write_vaddr; /* target virtual addr at which the
53
                                      memory was written */
46 54
} CPUSPARCState;
47 55

  
48 56
CPUSPARCState *cpu_sparc_init(void);

Also available in: Unified diff