VirtualBox

Changeset 36170 in vbox for trunk/src/recompiler/exec.c


Ignore:
Timestamp:
Mar 4, 2011 12:49:02 PM (14 years ago)
Author:
vboxsync
Message:

rem: synced up to svn://svn.savannah.nongnu.org/qemu/trunk@6686 (repo UUID c046a42c-6fe2-441c-8c8c-71466251a162).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/recompiler/exec.c

    r36140 r36170  
    1616 * You should have received a copy of the GNU Lesser General Public
    1717 * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
     18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
    1919 */
    2020
     
    6161#endif
    6262#include "osdep.h"
     63#include "kvm.h"
    6364#if defined(CONFIG_USER_ONLY)
    6465#include <qemu.h>
     
    149150   causes some pages to fall outside the dirty map here. */
    150151RTGCPHYS phys_ram_dirty_size;
     152uint8_t *phys_ram_dirty;
    151153#endif /* VBOX */
    152 #if !defined(VBOX)
    153 uint8_t *phys_ram_base;
    154 #endif
    155 uint8_t *phys_ram_dirty;
    156154
    157155CPUState *first_cpu;
     
    182180    /* offset in host memory of the page + io_index in the low bits */
    183181    ram_addr_t phys_offset;
     182    ram_addr_t region_offset;
    184183} PhysPageDesc;
    185184
     
    226225CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
    227226void *io_mem_opaque[IO_MEM_NB_ENTRIES];
    228 static int io_mem_nb;
     227char io_mem_used[IO_MEM_NB_ENTRIES];
    229228static int io_mem_watch;
    230229#endif
     
    257256    CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
    258257    void *opaque[TARGET_PAGE_SIZE][2][4];
     258    ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
    259259} subpage_t;
    260260
     
    305305    {
    306306        SYSTEM_INFO system_info;
    307         DWORD old_protect;
    308307
    309308        GetSystemInfo(&system_info);
     
    314313#endif
    315314#endif /* !VBOX */
    316 
    317315    if (qemu_host_page_size == 0)
    318316        qemu_host_page_size = qemu_real_host_page_size;
     
    406404        /* allocate if not found */
    407405#if defined(CONFIG_USER_ONLY)
    408         unsigned long addr;
    409406        size_t len = sizeof(PageDesc) * L2_SIZE;
    410407        /* Don't use qemu_malloc because it may recurse.  */
     
    412409                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    413410        *lp = p;
    414         addr = h2g(p);
    415         if (addr == (target_ulong)addr) {
     411        if (h2g_valid(p)) {
     412            unsigned long addr = h2g(p);
    416413            page_set_flags(addr & TARGET_PAGE_MASK,
    417414                           TARGET_PAGE_ALIGN(addr + len),
     
    486483        pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
    487484        *lp = pd;
    488         for (i = 0; i < L2_SIZE; i++)
     485        for (i = 0; i < L2_SIZE; i++) {
    489486          pd[i].phys_offset = IO_MEM_UNASSIGNED;
     487          pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
     488        }
    490489    }
    491490    return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
     
    545544        code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
    546545#else
    547         /* XXX: needs adjustments */
     546        /* XXX: needs ajustments */
    548547        code_gen_buffer_size = (unsigned long)(phys_ram_size / 4);
    549548#endif
    550 
    551549    }
    552550    if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
    553551        code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
    554552#endif /* VBOX */
    555 
    556553    /* The code gen buffer location may have constraints depending on
    557554       the host cpu and OS */
     
    564561        return;
    565562    }
    566 #else //!VBOX
     563#else  /* !VBOX */
    567564#if defined(__linux__)
    568565    {
     
    582579        if (code_gen_buffer_size > (512 * 1024 * 1024))
    583580            code_gen_buffer_size = (512 * 1024 * 1024);
     581#elif defined(__arm__)
     582        /* Map the buffer below 32M, so we can use direct calls and branches */
     583        flags |= MAP_FIXED;
     584        start = (void *) 0x01000000UL;
     585        if (code_gen_buffer_size > 16 * 1024 * 1024)
     586            code_gen_buffer_size = 16 * 1024 * 1024;
    584587#endif
    585588        code_gen_buffer = mmap(start, code_gen_buffer_size,
     
    615618#else
    616619    code_gen_buffer = qemu_malloc(code_gen_buffer_size);
    617     if (!code_gen_buffer) {
    618         fprintf(stderr, "Could not allocate dynamic translator buffer\n");
    619         exit(1);
    620     }
    621620    map_exec(code_gen_buffer, code_gen_buffer_size);
    622621#endif
    623     map_exec(code_gen_prologue, sizeof(code_gen_prologue));
    624622#endif /* !VBOX */
    625623#endif /* !USE_STATIC_CODE_GEN_BUFFER */
     
    629627    map_exec(code_gen_prologue, _1K);
    630628#endif
    631 
    632629    code_gen_buffer_max_size = code_gen_buffer_size -
    633630        code_gen_max_block_size();
     
    677674}
    678675#endif
    679 #endif //!VBOX
     676#endif /* !VBOX */
    680677
    681678void cpu_exec_init(CPUState *env)
     
    692689    }
    693690    env->cpu_index = cpu_index;
    694     env->nb_watchpoints = 0;
     691    TAILQ_INIT(&env->breakpoints);
     692    TAILQ_INIT(&env->watchpoints);
    695693    *penv = env;
    696694#ifndef VBOX
     
    701699                    cpu_save, cpu_load, env);
    702700#endif
    703 #endif // !VBOX
     701#endif /* !VBOX */
    704702}
    705703
     
    780778
    781779#ifdef DEBUG_TB_CHECK
     780
    782781static void tb_invalidate_check(target_ulong address)
    783782{
     
    10401039
    10411040    p->code_bitmap = qemu_mallocz(TARGET_PAGE_SIZE / 8);
    1042     if (!p->code_bitmap)
    1043         return;
    10441041
    10451042    tb = p->first_tb;
     
    11091106                                   int is_cpu_write_access)
    11101107{
    1111     int n, current_tb_modified, current_tb_not_found, current_flags;
     1108    TranslationBlock *tb, *tb_next, *saved_tb;
    11121109    CPUState *env = cpu_single_env;
     1110    target_ulong tb_start, tb_end;
    11131111    PageDesc *p;
    1114     TranslationBlock *tb, *tb_next, *current_tb, *saved_tb;
    1115     target_ulong tb_start, tb_end;
    1116     target_ulong current_pc, current_cs_base;
     1112    int n;
     1113#ifdef TARGET_HAS_PRECISE_SMC
     1114    int current_tb_not_found = is_cpu_write_access;
     1115    TranslationBlock *current_tb = NULL;
     1116    int current_tb_modified = 0;
     1117    target_ulong current_pc = 0;
     1118    target_ulong current_cs_base = 0;
     1119    int current_flags = 0;
     1120#endif /* TARGET_HAS_PRECISE_SMC */
    11171121
    11181122    p = page_find(start >> TARGET_PAGE_BITS);
     
    11281132    /* we remove all the TBs in the range [start, end[ */
    11291133    /* XXX: see if in some cases it could be faster to invalidate all the code */
    1130     current_tb_not_found = is_cpu_write_access;
    1131     current_tb_modified = 0;
    1132     current_tb = NULL; /* avoid warning */
    1133     current_pc = 0; /* avoid warning */
    1134     current_cs_base = 0; /* avoid warning */
    1135     current_flags = 0; /* avoid warning */
    11361134    tb = p->first_tb;
    11371135    while (tb != NULL) {
     
    11701168                cpu_restore_state(current_tb, env,
    11711169                                  env->mem_io_pc, NULL);
    1172 #if defined(TARGET_I386)
    1173                 current_flags = env->hflags;
    1174                 current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
    1175                 current_cs_base = (target_ulong)env->segs[R_CS].base;
    1176                 current_pc = current_cs_base + env->eip;
    1177 #else
    1178 #error unsupported CPU
    1179 #endif
     1170                cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
     1171                                     &current_flags);
    11801172            }
    11811173#endif /* TARGET_HAS_PRECISE_SMC */
     
    12171209}
    12181210
    1219 
    12201211/* len must be <= 8 and start must be a multiple of len */
    12211212static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
     
    12251216#if 0
    12261217    if (1) {
    1227         if (loglevel) {
    1228             fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
    1229                    cpu_single_env->mem_io_vaddr, len,
    1230                    cpu_single_env->eip,
    1231                    cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
    1232         }
     1218        qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
     1219                  cpu_single_env->mem_io_vaddr, len,
     1220                  cpu_single_env->eip,
     1221                  cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
    12331222    }
    12341223#endif
     
    12471236}
    12481237
    1249 
    12501238#if !defined(CONFIG_SOFTMMU)
    12511239static void tb_invalidate_phys_page(target_phys_addr_t addr,
    12521240                                    unsigned long pc, void *puc)
    12531241{
    1254     int n, current_flags, current_tb_modified;
    1255     target_ulong current_pc, current_cs_base;
     1242    TranslationBlock *tb;
    12561243    PageDesc *p;
    1257     TranslationBlock *tb, *current_tb;
     1244    int n;
    12581245#ifdef TARGET_HAS_PRECISE_SMC
     1246    TranslationBlock *current_tb = NULL;
    12591247    CPUState *env = cpu_single_env;
     1248    int current_tb_modified = 0;
     1249    target_ulong current_pc = 0;
     1250    target_ulong current_cs_base = 0;
     1251    int current_flags = 0;
    12601252#endif
    12611253
     
    12651257        return;
    12661258    tb = p->first_tb;
    1267     current_tb_modified = 0;
    1268     current_tb = NULL;
    1269     current_pc = 0; /* avoid warning */
    1270     current_cs_base = 0; /* avoid warning */
    1271     current_flags = 0; /* avoid warning */
    12721259#ifdef TARGET_HAS_PRECISE_SMC
    12731260    if (tb && pc != 0) {
     
    12891276            current_tb_modified = 1;
    12901277            cpu_restore_state(current_tb, env, pc, puc);
    1291 #if defined(TARGET_I386)
    1292             current_flags = env->hflags;
    1293             current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
    1294             current_cs_base = (target_ulong)env->segs[R_CS].base;
    1295             current_pc = current_cs_base + env->eip;
    1296 #else
    1297 #error unsupported CPU
    1298 #endif
     1278            cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
     1279                                 &current_flags);
    12991280        }
    13001281#endif /* TARGET_HAS_PRECISE_SMC */
     
    15401521
    15411522/* Add a watchpoint.  */
    1542 int cpu_watchpoint_insert(CPUState *env, target_ulong addr, int type)
    1543 {
    1544     int i;
    1545 
    1546     for (i = 0; i < env->nb_watchpoints; i++) {
    1547         if (addr == env->watchpoint[i].vaddr)
     1523int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
     1524                          int flags, CPUWatchpoint **watchpoint)
     1525{
     1526    target_ulong len_mask = ~(len - 1);
     1527    CPUWatchpoint *wp;
     1528
     1529    /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
     1530    if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
     1531        fprintf(stderr, "qemu: tried to set invalid watchpoint at "
     1532                TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
     1533#ifndef VBOX
     1534        return -EINVAL;
     1535#else
     1536        return VERR_INVALID_PARAMETER;
     1537#endif
     1538    }
     1539    wp = qemu_malloc(sizeof(*wp));
     1540
     1541    wp->vaddr = addr;
     1542    wp->len_mask = len_mask;
     1543    wp->flags = flags;
     1544
     1545    /* keep all GDB-injected watchpoints in front */
     1546    if (flags & BP_GDB)
     1547        TAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
     1548    else
     1549        TAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
     1550
     1551    tlb_flush_page(env, addr);
     1552
     1553    if (watchpoint)
     1554        *watchpoint = wp;
     1555    return 0;
     1556}
     1557
     1558/* Remove a specific watchpoint.  */
     1559int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
     1560                          int flags)
     1561{
     1562    target_ulong len_mask = ~(len - 1);
     1563    CPUWatchpoint *wp;
     1564
     1565    TAILQ_FOREACH(wp, &env->watchpoints, entry) {
     1566        if (addr == wp->vaddr && len_mask == wp->len_mask
     1567                && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
     1568            cpu_watchpoint_remove_by_ref(env, wp);
    15481569            return 0;
    1549     }
    1550     if (env->nb_watchpoints >= MAX_WATCHPOINTS)
    1551         return -1;
    1552 
    1553     i = env->nb_watchpoints++;
    1554     env->watchpoint[i].vaddr = addr;
    1555     env->watchpoint[i].type = type;
    1556     tlb_flush_page(env, addr);
    1557     /* FIXME: This flush is needed because of the hack to make memory ops
    1558        terminate the TB.  It can be removed once the proper IO trap and
    1559        re-execute bits are in.  */
    1560     tb_flush(env);
    1561     return i;
    1562 }
    1563 
    1564 /* Remove a watchpoint.  */
    1565 int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
    1566 {
    1567     int i;
    1568 
    1569     for (i = 0; i < env->nb_watchpoints; i++) {
    1570         if (addr == env->watchpoint[i].vaddr) {
    1571             env->nb_watchpoints--;
    1572             env->watchpoint[i] = env->watchpoint[env->nb_watchpoints];
    1573             tlb_flush_page(env, addr);
     1570        }
     1571    }
     1572#ifndef VBOX
     1573    return -ENOENT;
     1574#else
     1575    return VERR_NOT_FOUND;
     1576#endif
     1577}
     1578
     1579/* Remove a specific watchpoint by reference.  */
     1580void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
     1581{
     1582    TAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
     1583
     1584    tlb_flush_page(env, watchpoint->vaddr);
     1585
     1586    qemu_free(watchpoint);
     1587}
     1588
     1589/* Remove all matching watchpoints.  */
     1590void cpu_watchpoint_remove_all(CPUState *env, int mask)
     1591{
     1592    CPUWatchpoint *wp, *next;
     1593
     1594    TAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
     1595        if (wp->flags & mask)
     1596            cpu_watchpoint_remove_by_ref(env, wp);
     1597    }
     1598}
     1599
     1600/* Add a breakpoint.  */
     1601int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
     1602                          CPUBreakpoint **breakpoint)
     1603{
     1604#if defined(TARGET_HAS_ICE)
     1605    CPUBreakpoint *bp;
     1606
     1607    bp = qemu_malloc(sizeof(*bp));
     1608
     1609    bp->pc = pc;
     1610    bp->flags = flags;
     1611
     1612    /* keep all GDB-injected breakpoints in front */
     1613    if (flags & BP_GDB)
     1614        TAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
     1615    else
     1616        TAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
     1617
     1618    breakpoint_invalidate(env, pc);
     1619
     1620    if (breakpoint)
     1621        *breakpoint = bp;
     1622    return 0;
     1623#else
     1624    return -ENOSYS;
     1625#endif
     1626}
     1627
     1628/* Remove a specific breakpoint.  */
     1629int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
     1630{
     1631#if defined(TARGET_HAS_ICE)
     1632    CPUBreakpoint *bp;
     1633
     1634    TAILQ_FOREACH(bp, &env->breakpoints, entry) {
     1635        if (bp->pc == pc && bp->flags == flags) {
     1636            cpu_breakpoint_remove_by_ref(env, bp);
    15741637            return 0;
    15751638        }
    15761639    }
    1577     return -1;
    1578 }
    1579 
    1580 /* Remove all watchpoints. */
    1581 void cpu_watchpoint_remove_all(CPUState *env) {
    1582     int i;
    1583 
    1584     for (i = 0; i < env->nb_watchpoints; i++) {
    1585         tlb_flush_page(env, env->watchpoint[i].vaddr);
    1586     }
    1587     env->nb_watchpoints = 0;
    1588 }
    1589 
    1590 /* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
    1591    breakpoint is reached */
    1592 int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
     1640# ifndef VBOX
     1641    return -ENOENT;
     1642# else
     1643    return VERR_NOT_FOUND;
     1644# endif
     1645#else
     1646    return -ENOSYS;
     1647#endif
     1648}
     1649
     1650/* Remove a specific breakpoint by reference.  */
     1651void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
    15931652{
    15941653#if defined(TARGET_HAS_ICE)
    1595     int i;
    1596 
    1597     for(i = 0; i < env->nb_breakpoints; i++) {
    1598         if (env->breakpoints[i] == pc)
    1599             return 0;
    1600     }
    1601 
    1602     if (env->nb_breakpoints >= MAX_BREAKPOINTS)
    1603         return -1;
    1604     env->breakpoints[env->nb_breakpoints++] = pc;
    1605 
    1606     breakpoint_invalidate(env, pc);
    1607     return 0;
    1608 #else
    1609     return -1;
    1610 #endif
    1611 }
    1612 
    1613 /* remove all breakpoints */
    1614 void cpu_breakpoint_remove_all(CPUState *env) {
     1654    TAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
     1655
     1656    breakpoint_invalidate(env, breakpoint->pc);
     1657
     1658    qemu_free(breakpoint);
     1659#endif
     1660}
     1661
     1662/* Remove all matching breakpoints. */
     1663void cpu_breakpoint_remove_all(CPUState *env, int mask)
     1664{
    16151665#if defined(TARGET_HAS_ICE)
    1616     int i;
    1617     for(i = 0; i < env->nb_breakpoints; i++) {
    1618         breakpoint_invalidate(env, env->breakpoints[i]);
    1619     }
    1620     env->nb_breakpoints = 0;
    1621 #endif
    1622 }
    1623 
    1624 /* remove a breakpoint */
    1625 int cpu_breakpoint_remove(CPUState *env, target_ulong pc)
    1626 {
    1627 #if defined(TARGET_HAS_ICE)
    1628     int i;
    1629     for(i = 0; i < env->nb_breakpoints; i++) {
    1630         if (env->breakpoints[i] == pc)
    1631             goto found;
    1632     }
    1633     return -1;
    1634  found:
    1635     env->nb_breakpoints--;
    1636     if (i < env->nb_breakpoints)
    1637       env->breakpoints[i] = env->breakpoints[env->nb_breakpoints];
    1638 
    1639     breakpoint_invalidate(env, pc);
    1640     return 0;
    1641 #else
    1642     return -1;
     1666    CPUBreakpoint *bp, *next;
     1667
     1668    TAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
     1669        if (bp->flags & mask)
     1670            cpu_breakpoint_remove_by_ref(env, bp);
     1671    }
    16431672#endif
    16441673}
     
    17581787
    17591788#ifndef VBOX
    1760 CPULogItem cpu_log_items[] = {
     1789const CPULogItem cpu_log_items[] = {
    17611790    { CPU_LOG_TB_OUT_ASM, "out_asm",
    17621791      "show generated host assembly code for each compiled TB" },
     
    17801809    { CPU_LOG_PCALL, "pcall",
    17811810      "show protected mode far calls/returns/exceptions" },
     1811    { CPU_LOG_RESET, "cpu_reset",
     1812      "show CPU state before CPU resets" },
    17821813#endif
    17831814#ifdef DEBUG_IOPORT
     
    18451876    cpu_dump_state(env, stderr, fprintf, 0);
    18461877#endif
    1847     if (logfile) {
    1848         fprintf(logfile, "qemu: fatal: ");
    1849         vfprintf(logfile, fmt, ap2);
    1850         fprintf(logfile, "\n");
     1878    if (qemu_log_enabled()) {
     1879        qemu_log("qemu: fatal: ");
     1880        qemu_log_vprintf(fmt, ap2);
     1881        qemu_log("\n");
    18511882#ifdef TARGET_I386
    1852         cpu_dump_state(env, logfile, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
    1853 #else
    1854         cpu_dump_state(env, logfile, fprintf, 0);
    1855 #endif
    1856         fflush(logfile);
    1857         fclose(logfile);
     1883        log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
     1884#else
     1885        log_cpu_state(env, 0);
     1886#endif
     1887        qemu_log_flush();
     1888        qemu_log_close();
    18581889    }
    18591890    va_end(ap2);
     
    18671898{
    18681899    CPUState *new_env = cpu_init(env->cpu_model_str);
    1869     /* preserve chaining and index */
    18701900    CPUState *next_cpu = new_env->next_cpu;
    18711901    int cpu_index = new_env->cpu_index;
     1902#if defined(TARGET_HAS_ICE)
     1903    CPUBreakpoint *bp;
     1904    CPUWatchpoint *wp;
     1905#endif
     1906
    18721907    memcpy(new_env, env, sizeof(CPUState));
     1908
     1909    /* Preserve chaining and index. */
    18731910    new_env->next_cpu = next_cpu;
    18741911    new_env->cpu_index = cpu_index;
     1912
     1913    /* Clone all break/watchpoints.
     1914       Note: Once we support ptrace with hw-debug register access, make sure
     1915       BP_CPU break/watchpoints are handled correctly on clone. */
     1916    TAILQ_INIT(&env->breakpoints);
     1917    TAILQ_INIT(&env->watchpoints);
     1918#if defined(TARGET_HAS_ICE)
     1919    TAILQ_FOREACH(bp, &env->breakpoints, entry) {
     1920        cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
     1921    }
     1922    TAILQ_FOREACH(wp, &env->watchpoints, entry) {
     1923        cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
     1924                              wp->flags, NULL);
     1925    }
     1926#endif
     1927
    18751928    return new_env;
    18761929}
     
    21182171    return in_migration;
    21192172}
    2120 #endif
     2173#endif /* !VBOX */
     2174
     2175void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr)
     2176{
     2177    if (kvm_enabled())
     2178        kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
     2179}
    21212180
    21222181#if defined(VBOX) && !defined(REM_PHYS_ADDR_IN_TLB)
     
    21542213    for(i = 0; i < CPU_TLB_SIZE; i++)
    21552214        tlb_update_dirty(&env->tlb_table[1][i], env->phys_addends[1][i]);
    2156 #if (NB_MMU_MODES >= 3)
     2215# if (NB_MMU_MODES >= 3)
    21572216    for(i = 0; i < CPU_TLB_SIZE; i++)
    21582217        tlb_update_dirty(&env->tlb_table[2][i], env->phys_addends[2][i]);
    2159 #if (NB_MMU_MODES == 4)
     2218#  if (NB_MMU_MODES == 4)
    21602219    for(i = 0; i < CPU_TLB_SIZE; i++)
    21612220        tlb_update_dirty(&env->tlb_table[3][i], env->phys_addends[3][i]);
    2162 #endif
    2163 #endif
     2221#  endif
     2222# endif
    21642223#else /* VBOX */
    21652224    for(i = 0; i < CPU_TLB_SIZE; i++)
     
    22182277    int ret;
    22192278    CPUTLBEntry *te;
    2220     int i;
     2279    CPUWatchpoint *wp;
    22212280    target_phys_addr_t iotlb;
    22222281#if defined(VBOX) && !defined(REM_PHYS_ADDR_IN_TLB)
     
    22672326           We can't use the high bits of pd for this because
    22682327           IO_MEM_ROMD uses these as a ram address.  */
    2269         iotlb = (pd & ~TARGET_PAGE_MASK) + paddr;
     2328        iotlb = (pd & ~TARGET_PAGE_MASK);
     2329#ifndef VBOX
     2330        if (p) {
     2331#else
     2332        if (   p->phys_offset
     2333            && (pd & ~TARGET_PAGE_MASK) != env->pVM->rem.s.iMMIOMemType
     2334            && (pd & ~TARGET_PAGE_MASK) != env->pVM->rem.s.iHandlerMemType) {
     2335#endif
     2336            iotlb += p->region_offset;
     2337        } else {
     2338            iotlb += paddr;
     2339        }
    22702340    }
    22712341
     
    22992369    /* Make accesses to pages with watchpoints go via the
    23002370       watchpoint trap routines.  */
    2301     for (i = 0; i < env->nb_watchpoints; i++) {
    2302         if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) {
     2371    TAILQ_FOREACH(wp, &env->watchpoints, entry) {
     2372        if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
    23032373            iotlb = io_mem_watch + paddr;
    23042374            /* TODO: The memory case can be optimized by not trapping
     
    24672537    target_ulong addr;
    24682538
     2539    if (start + len < start)
     2540        /* we've wrapped around */
     2541        return -1;
     2542
    24692543    end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
    24702544    start = start & TARGET_PAGE_MASK;
    24712545
    2472     if( end < start )
    2473         /* we've wrapped around */
    2474         return -1;
    24752546    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
    24762547        p = page_find(addr >> TARGET_PAGE_BITS);
     
    25532624
    25542625#if !defined(CONFIG_USER_ONLY)
     2626
    25552627static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
    2556                              ram_addr_t memory);
     2628                             ram_addr_t memory, ram_addr_t region_offset);
    25572629static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
    2558                            ram_addr_t orig_memory);
     2630                           ram_addr_t orig_memory, ram_addr_t region_offset);
    25592631#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
    25602632                      need_subpage)                                     \
     
    25792651/* register physical memory. 'size' must be a multiple of the target
    25802652   page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
    2581    io memory page */
    2582 void cpu_register_physical_memory(target_phys_addr_t start_addr,
    2583                                   ram_addr_t size,
    2584                                   ram_addr_t phys_offset)
     2653   io memory page.  The address used when calling the IO function is
     2654   the offset from the start of the region, plus region_offset.  Both
     2655   start_region and regon_offset are rounded down to a page boundary
     2656   before calculating this offset.  This should not be a problem unless
     2657   the low bits of start_addr and region_offset differ.  */
     2658void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
     2659                                         ram_addr_t size,
     2660                                         ram_addr_t phys_offset,
     2661                                         ram_addr_t region_offset)
    25852662{
    25862663    target_phys_addr_t addr, end_addr;
     
    25972674    }
    25982675#endif
     2676    if (kvm_enabled())
     2677        kvm_set_phys_mem(start_addr, size, phys_offset);
     2678
     2679    if (phys_offset == IO_MEM_UNASSIGNED) {
     2680        region_offset = start_addr;
     2681    }
     2682    region_offset &= TARGET_PAGE_MASK;
    25992683    size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
    26002684    end_addr = start_addr + (target_phys_addr_t)size;
     
    26112695                if (!(orig_memory & IO_MEM_SUBPAGE)) {
    26122696                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
    2613                                            &p->phys_offset, orig_memory);
     2697                                           &p->phys_offset, orig_memory,
     2698                                           p->region_offset);
    26142699                } else {
    26152700                    subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
    26162701                                            >> IO_MEM_SHIFT];
    26172702                }
    2618                 subpage_register(subpage, start_addr2, end_addr2, phys_offset);
     2703                subpage_register(subpage, start_addr2, end_addr2, phys_offset,
     2704                                 region_offset);
     2705                p->region_offset = 0;
    26192706            } else {
    26202707                p->phys_offset = phys_offset;
     
    26262713            p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
    26272714            p->phys_offset = phys_offset;
     2715            p->region_offset = region_offset;
    26282716            if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
    2629                 (phys_offset & IO_MEM_ROMD))
     2717                (phys_offset & IO_MEM_ROMD)) {
    26302718                phys_offset += TARGET_PAGE_SIZE;
    2631             else {
     2719            } else {
    26322720                target_phys_addr_t start_addr2, end_addr2;
    26332721                int need_subpage = 0;
     
    26382726                if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
    26392727                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
    2640                                            &p->phys_offset, IO_MEM_UNASSIGNED);
     2728                                           &p->phys_offset, IO_MEM_UNASSIGNED,
     2729                                           addr & TARGET_PAGE_MASK);
    26412730                    subpage_register(subpage, start_addr2, end_addr2,
    2642                                      phys_offset);
     2731                                     phys_offset, region_offset);
     2732                    p->region_offset = 0;
    26432733                }
    26442734            }
    26452735        }
     2736        region_offset += TARGET_PAGE_SIZE;
    26462737    }
    26472738
     
    26662757
    26672758#ifndef VBOX
     2759void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
     2760{
     2761    if (kvm_enabled())
     2762        kvm_coalesce_mmio_region(addr, size);
     2763}
     2764
     2765void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
     2766{
     2767    if (kvm_enabled())
     2768        kvm_uncoalesce_mmio_region(addr, size);
     2769}
     2770
    26682771/* XXX: better than nothing */
    26692772ram_addr_t qemu_ram_alloc(ram_addr_t size)
     
    26902793    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
    26912794#endif
    2692 #if defined(TARGET_SPARC) || defined(TARGET_CRIS)
     2795#if defined(TARGET_SPARC)
    26932796    do_unassigned_access(addr, 0, 0, 0, 1);
    26942797#endif
     
    27012804    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
    27022805#endif
    2703 #if defined(TARGET_SPARC) || defined(TARGET_CRIS)
     2806#if defined(TARGET_SPARC)
    27042807    do_unassigned_access(addr, 0, 0, 0, 2);
    27052808#endif
     
    27122815    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
    27132816#endif
    2714 #if defined(TARGET_SPARC) || defined(TARGET_CRIS)
     2817#if defined(TARGET_SPARC)
    27152818    do_unassigned_access(addr, 0, 0, 0, 4);
    27162819#endif
     
    27232826    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
    27242827#endif
    2725 #if defined(TARGET_SPARC) || defined(TARGET_CRIS)
     2828#if defined(TARGET_SPARC)
    27262829    do_unassigned_access(addr, 1, 0, 0, 1);
    27272830#endif
     
    27332836    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
    27342837#endif
    2735 #if defined(TARGET_SPARC) || defined(TARGET_CRIS)
     2838#if defined(TARGET_SPARC)
    27362839    do_unassigned_access(addr, 1, 0, 0, 2);
    27372840#endif
     
    27432846    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
    27442847#endif
    2745 #if defined(TARGET_SPARC) || defined(TARGET_CRIS)
     2848#if defined(TARGET_SPARC)
    27462849    do_unassigned_access(addr, 1, 0, 0, 4);
    27472850#endif
     
    28282931    stw_p(phys_ram_base + ram_addr, val);
    28292932#endif
    2830 
    28312933#ifdef USE_KQEMU
    28322934    if (cpu_single_env->kqemu_enabled &&
     
    29003002
    29013003/* Generate a debug exception if a watchpoint has been hit.  */
    2902 static void check_watchpoint(int offset, int flags)
     3004static void check_watchpoint(int offset, int len_mask, int flags)
    29033005{
    29043006    CPUState *env = cpu_single_env;
     3007    target_ulong pc, cs_base;
     3008    TranslationBlock *tb;
    29053009    target_ulong vaddr;
    2906     int i;
    2907 
     3010    CPUWatchpoint *wp;
     3011    int cpu_flags;
     3012
     3013    if (env->watchpoint_hit) {
     3014        /* We re-entered the check after replacing the TB. Now raise
     3015         * the debug interrupt so that is will trigger after the
     3016         * current instruction. */
     3017        cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
     3018        return;
     3019    }
    29083020    vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
    2909     for (i = 0; i < env->nb_watchpoints; i++) {
    2910         if (vaddr == env->watchpoint[i].vaddr
    2911                 && (env->watchpoint[i].type & flags)) {
    2912             env->watchpoint_hit = i + 1;
    2913             cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
    2914             break;
     3021    TAILQ_FOREACH(wp, &env->watchpoints, entry) {
     3022        if ((vaddr == (wp->vaddr & len_mask) ||
     3023             (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
     3024            wp->flags |= BP_WATCHPOINT_HIT;
     3025            if (!env->watchpoint_hit) {
     3026                env->watchpoint_hit = wp;
     3027                tb = tb_find_pc(env->mem_io_pc);
     3028                if (!tb) {
     3029                    cpu_abort(env, "check_watchpoint: could not find TB for "
     3030                              "pc=%p", (void *)env->mem_io_pc);
     3031                }
     3032                cpu_restore_state(tb, env, env->mem_io_pc, NULL);
     3033                tb_phys_invalidate(tb, -1);
     3034                if (wp->flags & BP_STOP_BEFORE_ACCESS) {
     3035                    env->exception_index = EXCP_DEBUG;
     3036                } else {
     3037                    cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
     3038                    tb_gen_code(env, pc, cs_base, cpu_flags, 1);
     3039                }
     3040                cpu_resume_from_signal(env, NULL);
     3041            }
     3042        } else {
     3043            wp->flags &= ~BP_WATCHPOINT_HIT;
    29153044        }
    29163045    }
     
    29223051static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
    29233052{
    2924     check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
     3053    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
    29253054    return ldub_phys(addr);
    29263055}
     
    29283057static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
    29293058{
    2930     check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
     3059    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
    29313060    return lduw_phys(addr);
    29323061}
     
    29343063static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
    29353064{
    2936     check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
     3065    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
    29373066    return ldl_phys(addr);
    29383067}
     
    29413070                             uint32_t val)
    29423071{
    2943     check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
     3072    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
    29443073    stb_phys(addr, val);
    29453074}
     
    29483077                             uint32_t val)
    29493078{
    2950     check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
     3079    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
    29513080    stw_phys(addr, val);
    29523081}
     
    29553084                             uint32_t val)
    29563085{
    2957     check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
     3086    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
    29583087    stl_phys(addr, val);
    29593088}
     
    29773106    unsigned int idx;
    29783107
    2979     idx = SUBPAGE_IDX(addr - mmio->base);
     3108    idx = SUBPAGE_IDX(addr);
    29803109#if defined(DEBUG_SUBPAGE)
    29813110    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
    29823111           mmio, len, addr, idx);
    29833112#endif
    2984     ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len], addr);
     3113    ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
     3114                                       addr + mmio->region_offset[idx][0][len]);
    29853115
    29863116    return ret;
     
    29923122    unsigned int idx;
    29933123
    2994     idx = SUBPAGE_IDX(addr - mmio->base);
     3124    idx = SUBPAGE_IDX(addr);
    29953125#if defined(DEBUG_SUBPAGE)
    29963126    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
    29973127           mmio, len, addr, idx, value);
    29983128#endif
    2999     (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len], addr, value);
     3129    (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
     3130                                  addr + mmio->region_offset[idx][1][len],
     3131                                  value);
    30003132}
    30013133
     
    30673199
    30683200static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
    3069                              ram_addr_t memory)
     3201                             ram_addr_t memory, ram_addr_t region_offset)
    30703202{
    30713203    int idx, eidx;
     
    30863218                mmio->mem_read[idx][i] = &io_mem_read[memory][i];
    30873219                mmio->opaque[idx][0][i] = io_mem_opaque[memory];
     3220                mmio->region_offset[idx][0][i] = region_offset;
    30883221            }
    30893222            if (io_mem_write[memory][i]) {
    30903223                mmio->mem_write[idx][i] = &io_mem_write[memory][i];
    30913224                mmio->opaque[idx][1][i] = io_mem_opaque[memory];
     3225                mmio->region_offset[idx][1][i] = region_offset;
    30923226            }
    30933227        }
     
    30983232
    30993233static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
    3100                            ram_addr_t orig_memory)
     3234                           ram_addr_t orig_memory, ram_addr_t region_offset)
    31013235{
    31023236    subpage_t *mmio;
     
    31043238
    31053239    mmio = qemu_mallocz(sizeof(subpage_t));
    3106     if (mmio != NULL) {
    3107         mmio->base = base;
    3108         subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, mmio);
     3240
     3241    mmio->base = base;
     3242    subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, mmio);
    31093243#if defined(DEBUG_SUBPAGE)
    3110         printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
    3111                mmio, base, TARGET_PAGE_SIZE, subpage_memory);
    3112 #endif
    3113         *phys = subpage_memory | IO_MEM_SUBPAGE;
    3114         subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory);
    3115     }
     3244    printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
     3245           mmio, base, TARGET_PAGE_SIZE, subpage_memory);
     3246#endif
     3247    *phys = subpage_memory | IO_MEM_SUBPAGE;
     3248    subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
     3249                         region_offset);
    31163250
    31173251    return mmio;
    31183252}
    31193253
     3254static int get_free_io_mem_idx(void)
     3255{
     3256    int i;
     3257
     3258    for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
     3259        if (!io_mem_used[i]) {
     3260            io_mem_used[i] = 1;
     3261            return i;
     3262        }
     3263
     3264    return -1;
     3265}
     3266
    31203267static void io_mem_init(void)
    31213268{
     3269    int i;
     3270
    31223271    cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
    31233272    cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
    31243273    cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
    3125     io_mem_nb = 5;
     3274    for (i=0; i<5; i++)
     3275        io_mem_used[i] = 1;
    31263276
    31273277    io_mem_watch = cpu_register_io_memory(0, watch_mem_read,
     
    31513301
    31523302    if (io_index <= 0) {
    3153         if (io_mem_nb >= IO_MEM_NB_ENTRIES)
    3154             return -1;
    3155         io_index = io_mem_nb++;
     3303        io_index = get_free_io_mem_idx();
     3304        if (io_index == -1)
     3305            return io_index;
    31563306    } else {
    31573307        if (io_index >= IO_MEM_NB_ENTRIES)
     
    31673317    io_mem_opaque[io_index] = opaque;
    31683318    return (io_index << IO_MEM_SHIFT) | subwidth;
     3319}
     3320
     3321void cpu_unregister_io_memory(int io_table_address)
     3322{
     3323    int i;
     3324    int io_index = io_table_address >> IO_MEM_SHIFT;
     3325
     3326    for (i=0;i < 3; i++) {
     3327        io_mem_read[io_index][i] = unassigned_mem_read[i];
     3328        io_mem_write[io_index][i] = unassigned_mem_write[i];
     3329    }
     3330    io_mem_opaque[io_index] = NULL;
     3331    io_mem_used[io_index] = 0;
    31693332}
    31703333
     
    32483411        if (is_write) {
    32493412            if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
     3413                target_phys_addr_t addr1 = addr;
    32503414                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     3415                if (p)
     3416                    addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
    32513417                /* XXX: could force cpu_single_env to NULL to avoid
    32523418                   potential bugs */
    3253                 if (l >= 4 && ((addr & 3) == 0)) {
     3419                if (l >= 4 && ((addr1 & 3) == 0)) {
    32543420                    /* 32 bit write access */
    32553421#if !defined(VBOX) || !defined(REM_PHYS_ADDR_IN_TLB)
     
    32583424                    val = *(const uint32_t *)buf;
    32593425#endif
    3260                     io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
     3426                    io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
    32613427                    l = 4;
    3262                 } else if (l >= 2 && ((addr & 1) == 0)) {
     3428                } else if (l >= 2 && ((addr1 & 1) == 0)) {
    32633429                    /* 16 bit write access */
    32643430#if !defined(VBOX) || !defined(REM_PHYS_ADDR_IN_TLB)
     
    32673433                    val = *(const uint16_t *)buf;
    32683434#endif
    3269                     io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
     3435                    io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
    32703436                    l = 2;
    32713437                } else {
     
    32763442                    val = *(const uint8_t *)buf;
    32773443#endif
    3278                     io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
     3444                    io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
    32793445                    l = 1;
    32803446                }
     
    33033469            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
    33043470                !(pd & IO_MEM_ROMD)) {
     3471                target_phys_addr_t addr1 = addr;
    33053472                /* I/O case */
    33063473                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
    3307                 if (l >= 4 && ((addr & 3) == 0)) {
     3474                if (p)
     3475                    addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
     3476                if (l >= 4 && ((addr1 & 3) == 0)) {
    33083477                    /* 32 bit read access */
    3309                     val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
     3478                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
    33103479#if !defined(VBOX) || !defined(REM_PHYS_ADDR_IN_TLB)
    33113480                    stl_p(buf, val);
     
    33143483#endif
    33153484                    l = 4;
    3316                 } else if (l >= 2 && ((addr & 1) == 0)) {
     3485                } else if (l >= 2 && ((addr1 & 1) == 0)) {
    33173486                    /* 16 bit read access */
    3318                     val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
     3487                    val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
    33193488#if !defined(VBOX) || !defined(REM_PHYS_ADDR_IN_TLB)
    33203489                    stw_p(buf, val);
     
    33253494                } else {
    33263495                    /* 8 bit read access */
    3327                     val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
     3496                    val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
    33283497#if !defined(VBOX) || !defined(REM_PHYS_ADDR_IN_TLB)
    33293498                    stb_p(buf, val);
     
    33513520
    33523521#ifndef VBOX
     3522
    33533523/* used for ROM loading : can write in RAM and ROM */
    33543524void cpu_physical_memory_write_rom(target_phys_addr_t addr,
     
    33893559    }
    33903560}
     3561
     3562typedef struct {
     3563    void *buffer;
     3564    target_phys_addr_t addr;
     3565    target_phys_addr_t len;
     3566} BounceBuffer;
     3567
     3568static BounceBuffer bounce;
     3569
     3570typedef struct MapClient {
     3571    void *opaque;
     3572    void (*callback)(void *opaque);
     3573    LIST_ENTRY(MapClient) link;
     3574} MapClient;
     3575
     3576static LIST_HEAD(map_client_list, MapClient) map_client_list
     3577    = LIST_HEAD_INITIALIZER(map_client_list);
     3578
     3579void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
     3580{
     3581    MapClient *client = qemu_malloc(sizeof(*client));
     3582
     3583    client->opaque = opaque;
     3584    client->callback = callback;
     3585    LIST_INSERT_HEAD(&map_client_list, client, link);
     3586    return client;
     3587}
     3588
     3589void cpu_unregister_map_client(void *_client)
     3590{
     3591    MapClient *client = (MapClient *)_client;
     3592
     3593    LIST_REMOVE(client, link);
     3594}
     3595
     3596static void cpu_notify_map_clients(void)
     3597{
     3598    MapClient *client;
     3599
     3600    while (!LIST_EMPTY(&map_client_list)) {
     3601        client = LIST_FIRST(&map_client_list);
     3602        client->callback(client->opaque);
     3603        LIST_REMOVE(client, link);
     3604    }
     3605}
     3606
     3607/* Map a physical memory region into a host virtual address.
     3608 * May map a subset of the requested range, given by and returned in *plen.
     3609 * May return NULL if resources needed to perform the mapping are exhausted.
     3610 * Use only for reads OR writes - not for read-modify-write operations.
     3611 * Use cpu_register_map_client() to know when retrying the map operation is
     3612 * likely to succeed.
     3613 */
     3614void *cpu_physical_memory_map(target_phys_addr_t addr,
     3615                              target_phys_addr_t *plen,
     3616                              int is_write)
     3617{
     3618    target_phys_addr_t len = *plen;
     3619    target_phys_addr_t done = 0;
     3620    int l;
     3621    uint8_t *ret = NULL;
     3622    uint8_t *ptr;
     3623    target_phys_addr_t page;
     3624    unsigned long pd;
     3625    PhysPageDesc *p;
     3626    unsigned long addr1;
     3627
     3628    while (len > 0) {
     3629        page = addr & TARGET_PAGE_MASK;
     3630        l = (page + TARGET_PAGE_SIZE) - addr;
     3631        if (l > len)
     3632            l = len;
     3633        p = phys_page_find(page >> TARGET_PAGE_BITS);
     3634        if (!p) {
     3635            pd = IO_MEM_UNASSIGNED;
     3636        } else {
     3637            pd = p->phys_offset;
     3638        }
     3639
     3640        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
     3641            if (done || bounce.buffer) {
     3642                break;
     3643            }
     3644            bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
     3645            bounce.addr = addr;
     3646            bounce.len = l;
     3647            if (!is_write) {
     3648                cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
     3649            }
     3650            ptr = bounce.buffer;
     3651        } else {
     3652            addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
     3653            ptr = phys_ram_base + addr1;
     3654        }
     3655        if (!done) {
     3656            ret = ptr;
     3657        } else if (ret + done != ptr) {
     3658            break;
     3659        }
     3660
     3661        len -= l;
     3662        addr += l;
     3663        done += l;
     3664    }
     3665    *plen = done;
     3666    return ret;
     3667}
     3668
     3669/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
     3670 * Will also mark the memory as dirty if is_write == 1.  access_len gives
     3671 * the amount of memory that was actually read or written by the caller.
     3672 */
     3673void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
     3674                               int is_write, target_phys_addr_t access_len)
     3675{
     3676    if (buffer != bounce.buffer) {
     3677        if (is_write) {
     3678            unsigned long addr1 = (uint8_t *)buffer - phys_ram_base;
     3679            while (access_len) {
     3680                unsigned l;
     3681                l = TARGET_PAGE_SIZE;
     3682                if (l > access_len)
     3683                    l = access_len;
     3684                if (!cpu_physical_memory_is_dirty(addr1)) {
     3685                    /* invalidate code */
     3686                    tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
     3687                    /* set dirty bit */
     3688                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
     3689                        (0xff & ~CODE_DIRTY_FLAG);
     3690                }
     3691                addr1 += l;
     3692                access_len -= l;
     3693            }
     3694        }
     3695        return;
     3696    }
     3697    if (is_write) {
     3698        cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
     3699    }
     3700    qemu_free(bounce.buffer);
     3701    bounce.buffer = NULL;
     3702    cpu_notify_map_clients();
     3703}
     3704
    33913705#endif /* !VBOX */
    3392 
    33933706
    33943707/* warning: addr must be aligned */
     
    34123725        /* I/O case */
    34133726        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     3727        if (p)
     3728            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
    34143729        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
    34153730    } else {
     
    34463761        /* I/O case */
    34473762        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     3763        if (p)
     3764            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
    34483765#ifdef TARGET_WORDS_BIGENDIAN
    34493766        val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
     
    35013818    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
    35023819        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     3820        if (p)
     3821            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
    35033822        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
    35043823    } else {
     
    35103829        remR3PhysWriteU32((pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK), val); NOREF(ptr);
    35113830#endif
     3831
    35123832#ifndef VBOX
    35133833        if (unlikely(in_migration)) {
     
    35403860    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
    35413861        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     3862        if (p)
     3863            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
    35423864#ifdef TARGET_WORDS_BIGENDIAN
    35433865        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
     
    35753897    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
    35763898        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     3899        if (p)
     3900            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
    35773901        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
    35783902    } else {
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette