18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  virtual page mapping and translated block handling
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  Copyright (c) 2003 Fabrice Bellard
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is free software; you can redistribute it and/or
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modify it under the terms of the GNU Lesser General Public
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * License as published by the Free Software Foundation; either
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * version 2 of the License, or (at your option) any later version.
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is distributed in the hope that it will be useful,
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Lesser General Public License for more details.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * You should have received a copy of the GNU Lesser General Public
17a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner * License along with this library; if not, see <http://www.gnu.org/licenses/>.
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "config.h"
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define WIN32_LEAN_AND_MEAN
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <windows.h>
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/types.h>
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/mman.h>
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdarg.h>
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <errno.h>
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <unistd.h>
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <inttypes.h>
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "cpu.h"
36852088c7e08182c2de563872d558309815cbfa0dDavid 'Digit' Turner#include "exec/exec-all.h"
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-common.h"
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcg.h"
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "hw/hw.h"
406234c0bcfcdd730c6815136cf958b240af8f4a7cDavid 'Digit' Turner#include "hw/qdev.h"
410e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#include "hw/xen/xen.h"
42845691383dd6a0ff71acf7aee0736adba350f6a9David 'Digit' Turner#include "qemu/osdep.h"
434ab1225535dfc5fbcbde37a171b39224ea34e30bDavid 'Digit' Turner#include "qemu/tls.h"
4434c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/kvm.h"
453dc53fc5342d24fae977049a40c34cc63ba04ad6David 'Digit' Turner#include "exec/cputlb.h"
46e1e03df288d5a44bfbffbd86588395c7cbbc27dfDavid 'Digit' Turner#include "exec/hax.h"
477a78db75ad42aea283f5073f51891464104a9fc3David 'Digit' Turner#include "qemu/timer.h"
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_USER_ONLY)
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <qemu.h>
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//#define DEBUG_SUBPAGE
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint phys_ram_fd;
565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int in_migration;
575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
580e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' TurnerRAMList ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) };
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
614ab1225535dfc5fbcbde37a171b39224ea34e30bDavid 'Digit' Turnerstruct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
624ab1225535dfc5fbcbde37a171b39224ea34e30bDavid 'Digit' TurnerDEFINE_TLS(CPUState *, current_cpu);
634ab1225535dfc5fbcbde37a171b39224ea34e30bDavid 'Digit' Turner
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 0 = Do not count executed instructions.
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   1 = Precise instruction counting.
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   2 = Adaptive rate instruction counting.  */
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint use_icount = 0;
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Current instruction counter.  While executing translated code this may
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   include some instructions that have not yet been executed.  */
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint64_t qemu_icount;
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void io_mem_init(void);
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* io memory support */
76fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' TurnerCPUWriteMemoryFunc *_io_mem_write[IO_MEM_NB_ENTRIES][4];
77fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' TurnerCPUReadMemoryFunc *_io_mem_read[IO_MEM_NB_ENTRIES][4];
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid *io_mem_opaque[IO_MEM_NB_ENTRIES];
795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic char io_mem_used[IO_MEM_NB_ENTRIES];
803dc53fc5342d24fae977049a40c34cc63ba04ad6David 'Digit' Turnerint io_mem_watch;
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* log support */
84a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#ifdef WIN32
85a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turnerstatic const char *logfilename = "qemu.log";
86a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#else
875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const char *logfilename = "/tmp/qemu.log";
88a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#endif
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectFILE *logfile;
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint loglevel;
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int log_append = 0;
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct subpage_t {
95bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner    hwaddr base;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *opaque[TARGET_PAGE_SIZE][2][4];
995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} subpage_t;
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Must be called before using the QEMU cpus. 'tb_size' is the size
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   (in bytes) allocated to the translation buffer. Zero means default
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   size. */
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_exec_init_all(unsigned long tb_size)
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
107ff9a2b851f95dff46171881afcdc65b2e164d36dDavid 'Digit' Turner    //cpu_gen_init();
108ff9a2b851f95dff46171881afcdc65b2e164d36dDavid 'Digit' Turner    //code_gen_alloc(tb_size);
109ff9a2b851f95dff46171881afcdc65b2e164d36dDavid 'Digit' Turner    //code_gen_ptr = code_gen_buffer;
110ff9a2b851f95dff46171881afcdc65b2e164d36dDavid 'Digit' Turner    //page_init();
111ff9a2b851f95dff46171881afcdc65b2e164d36dDavid 'Digit' Turner    tcg_exec_init(tb_size);
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
1130e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    qemu_mutex_init(&ram_list.mutex);
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    io_mem_init();
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define CPU_COMMON_SAVE_VERSION 1
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void cpu_common_save(QEMUFile *f, void *opaque)
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
124e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner    CPUOldState *env = opaque;
1256657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPUState *cpu = ENV_GET_CPU(env);
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
127e36a683b547e540c68bf9c5578e05b29c8676f47David 'Digit' Turner    cpu_synchronize_state(cpu, 0);
1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1296657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    qemu_put_be32s(f, &cpu->halted);
1306657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    qemu_put_be32s(f, &cpu->interrupt_request);
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
135e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner    CPUOldState *env = opaque;
1366657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPUState *cpu = ENV_GET_CPU(env);
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (version_id != CPU_COMMON_SAVE_VERSION)
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -EINVAL;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1416657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    qemu_get_be32s(f, &cpu->halted);
1426657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    qemu_get_be32s(f, &cpu->interrupt_request);
1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner       version_id is increased. */
1456657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    cpu->interrupt_request &= ~0x01;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tlb_flush(env, 1);
147e36a683b547e540c68bf9c5578e05b29c8676f47David 'Digit' Turner    cpu_synchronize_state(cpu, 1);
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
153bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' TurnerCPUState *qemu_get_cpu(int cpu_index)
1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1556657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPUState *cpu;
1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1576657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPU_FOREACH(cpu) {
1586657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner        if (cpu->cpu_index == cpu_index)
159bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner            return cpu;
1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
161bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner    return NULL;
1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1644d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnervoid cpu_exec_init(CPUArchState *env)
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1666657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPUState *cpu = ENV_GET_CPU(env);
1676657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner
1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(CONFIG_USER_ONLY)
1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_list_lock();
1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
1714ab1225535dfc5fbcbde37a171b39224ea34e30bDavid 'Digit' Turner    // Compute CPU index from list position.
1724ab1225535dfc5fbcbde37a171b39224ea34e30bDavid 'Digit' Turner    int cpu_index = 0;
1736657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPUState *cpu1;
1746657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPU_FOREACH(cpu1) {
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_index++;
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1776657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    cpu->cpu_index = cpu_index;
1786657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    QTAILQ_INSERT_TAIL(&cpus, cpu, node);
1794ab1225535dfc5fbcbde37a171b39224ea34e30bDavid 'Digit' Turner
1806657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    cpu->numa_node = 0;
181a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QTAILQ_INIT(&env->breakpoints);
182a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QTAILQ_INIT(&env->watchpoints);
1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(CONFIG_USER_ONLY)
1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_list_unlock();
1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
1875cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner    register_savevm(NULL,
1885cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    "cpu_common",
1895cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    cpu_index,
1905cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    CPU_COMMON_SAVE_VERSION,
1915cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    cpu_common_save,
1925cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    cpu_common_load,
1935cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    env);
1945cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner    register_savevm(NULL,
1955cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    "cpu",
1965cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    cpu_index,
1975cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    CPU_SAVE_VERSION,
1985cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    cpu_save,
1995cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    cpu_load,
2005cb5c0b8c5145dc0002b24e1421a3fa7a697475eDavid 'Digit' Turner                    env);
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_HAS_ICE)
2054d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnerstatic void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
207bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner    hwaddr addr;
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong pd;
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ram_addr_t ram_addr;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PhysPageDesc *p;
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    addr = cpu_get_phys_page_debug(env, pc);
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p) {
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pd = IO_MEM_UNASSIGNED;
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pd = p->phys_offset;
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22485c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner#if defined(CONFIG_USER_ONLY)
22585c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turnervoid cpu_watchpoint_remove_all(CPUArchState *env, int mask)
22685c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner
22785c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner{
22885c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner}
22985c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner
23085c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turnerint cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
23185c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner                          int flags, CPUWatchpoint **watchpoint)
23285c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner{
23385c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner    return -ENOSYS;
23485c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner}
23585c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner#else
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Add a watchpoint.  */
2374d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnerint cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                          int flags, CPUWatchpoint **watchpoint)
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    target_ulong len_mask = ~(len - 1);
2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUWatchpoint *wp;
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
24485c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner    if ((len & (len - 1)) || (addr & ~len_mask) ||
24585c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner            len == 0 || len > TARGET_PAGE_SIZE) {
2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "qemu: tried to set invalid watchpoint at "
2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EINVAL;
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
250aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    wp = g_malloc(sizeof(*wp));
2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    wp->vaddr = addr;
2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    wp->len_mask = len_mask;
2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    wp->flags = flags;
2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* keep all GDB-injected watchpoints in front */
2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (flags & BP_GDB)
258a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else
260a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tlb_flush_page(env, addr);
2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (watchpoint)
2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *watchpoint = wp;
2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Remove a specific watchpoint.  */
2704d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnerint cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                          int flags)
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    target_ulong len_mask = ~(len - 1);
2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUWatchpoint *wp;
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
276a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (addr == wp->vaddr && len_mask == wp->len_mask
2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            cpu_watchpoint_remove_by_ref(env, wp);
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return -ENOENT;
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Remove a specific watchpoint by reference.  */
2874d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnervoid cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
2885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
289a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tlb_flush_page(env, watchpoint->vaddr);
2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
293aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(watchpoint);
2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Remove all matching watchpoints.  */
2974d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnervoid cpu_watchpoint_remove_all(CPUArchState *env, int mask)
2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUWatchpoint *wp, *next;
3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
301a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (wp->flags & mask)
3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            cpu_watchpoint_remove_by_ref(env, wp);
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
30685c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner#endif
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Add a breakpoint.  */
3094d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnerint cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                          CPUBreakpoint **breakpoint)
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_HAS_ICE)
3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUBreakpoint *bp;
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
315aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    bp = g_malloc(sizeof(*bp));
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bp->pc = pc;
3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bp->flags = flags;
3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* keep all GDB-injected breakpoints in front */
32185c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner    if (flags & BP_GDB) {
322a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
32385c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner    } else {
324a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
32585c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner    }
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    breakpoint_invalidate(env, pc);
3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
32985c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner    if (breakpoint) {
3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *breakpoint = bp;
33185c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner    }
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return -ENOSYS;
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Remove a specific breakpoint.  */
3394d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnerint cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_HAS_ICE)
3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUBreakpoint *bp;
3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
344a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bp->pc == pc && bp->flags == flags) {
3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            cpu_breakpoint_remove_by_ref(env, bp);
3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return -ENOENT;
3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return -ENOSYS;
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Remove a specific breakpoint by reference.  */
3574d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnervoid cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_HAS_ICE)
360a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    breakpoint_invalidate(env, breakpoint->pc);
3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
364aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(breakpoint);
3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Remove all matching breakpoints. */
3694d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnervoid cpu_breakpoint_remove_all(CPUArchState *env, int mask)
3705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(TARGET_HAS_ICE)
3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUBreakpoint *bp, *next;
3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
374a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bp->flags & mask)
3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            cpu_breakpoint_remove_by_ref(env, bp);
3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* enable or disable single step mode. EXCP_DEBUG is returned by the
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   CPU loop after each instruction */
383fed223d2bab55eda155e3463b9cb6966e69dd73cDavid 'Digit' Turnervoid cpu_single_step(CPUState *cpu, int enabled)
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(TARGET_HAS_ICE)
386fed223d2bab55eda155e3463b9cb6966e69dd73cDavid 'Digit' Turner    if (cpu->singlestep_enabled != enabled) {
387fed223d2bab55eda155e3463b9cb6966e69dd73cDavid 'Digit' Turner        cpu->singlestep_enabled = enabled;
3888b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner        if (kvm_enabled()) {
389fed223d2bab55eda155e3463b9cb6966e69dd73cDavid 'Digit' Turner            kvm_update_guest_debug(cpu->env_ptr, 0);
3908b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner        } else {
3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* must flush all the translated code to avoid inconsistencies */
3925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* XXX: only flush what is necessary */
393fed223d2bab55eda155e3463b9cb6966e69dd73cDavid 'Digit' Turner            tb_flush(cpu->env_ptr);
3945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* enable or disable low levels log */
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_set_log(int log_flags)
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    loglevel = log_flags;
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (loglevel && !logfile) {
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logfile = fopen(logfilename, log_append ? "a" : "w");
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!logfile) {
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            perror(logfilename);
4074a2c9dd7630ce51a660e1aa14e10bc6fbc4621c4Iliyan Malchev            exit(1);
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_SOFTMMU)
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            static char logfile_buf[4096];
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
415a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#elif !defined(_WIN32)
416a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        /* Win32 doesn't support line-buffering and requires size >= 2 */
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        setvbuf(logfile, NULL, _IOLBF, 0);
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        log_append = 1;
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!loglevel && logfile) {
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fclose(logfile);
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logfile = NULL;
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_set_log_filename(const char *filename)
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    logfilename = strdup(filename);
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (logfile) {
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fclose(logfile);
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logfile = NULL;
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_set_log(loglevel);
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4373e0677df2819b1366819fe4112dc8464425b6edaDavid 'Digit' Turnervoid cpu_unlink_tb(CPUOldState *env)
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* FIXME: TB unchaining isn't SMP safe.  For now just ignore the
4405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner       problem and hope the cpu will stop of its own accord.  For userspace
4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner       emulation this often isn't actually as bad as it sounds.  Often
4425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner       signals are used primarily to interrupt blocking syscalls.  */
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
446795bb19daea966401df15bbf23c57b98848eec23David 'Digit' Turner    spin_lock(&interrupt_lock);
4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tb = env->current_tb;
4485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* if the cpu is currently executing code, we must unlink it and
4495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner       all the potentially executing TB */
450795bb19daea966401df15bbf23c57b98848eec23David 'Digit' Turner    if (tb) {
4515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        env->current_tb = NULL;
4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tb_reset_jump_recursive(tb);
4535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
454795bb19daea966401df15bbf23c57b98848eec23David 'Digit' Turner    spin_unlock(&interrupt_lock);
4555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
457bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turnervoid cpu_reset_interrupt(CPUState *cpu, int mask)
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4596657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    cpu->interrupt_request &= ~mask;
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
462bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turnervoid cpu_exit(CPUState *cpu)
4635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4646657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    cpu->exit_request = 1;
465bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner    cpu_unlink_tb(cpu->env_ptr);
4665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
46885c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turnervoid cpu_abort(CPUArchState *env, const char *fmt, ...)
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
470bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner    CPUState *cpu = ENV_GET_CPU(env);
471bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_list ap;
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_list ap2;
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start(ap, fmt);
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_copy(ap2, ap);
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fprintf(stderr, "qemu: fatal: ");
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vfprintf(stderr, fmt, ap);
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fprintf(stderr, "\n");
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TARGET_I386
481bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner    cpu_dump_state(cpu, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
483bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner    cpu_dump_state(cpu, stderr, fprintf, 0);
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (qemu_log_enabled()) {
4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log("qemu: fatal: ");
4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log_vprintf(fmt, ap2);
4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log("\n");
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TARGET_I386
490bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner        log_cpu_state(cpu, X86_DUMP_FPU | X86_DUMP_CCOP);
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
492bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner        log_cpu_state(cpu, 0);
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log_flush();
4955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log_close();
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end(ap2);
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end(ap);
4993641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turner#if defined(CONFIG_USER_ONLY)
5003641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turner    {
5013641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turner        struct sigaction act;
5023641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turner        sigfillset(&act.sa_mask);
5033641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turner        act.sa_handler = SIG_DFL;
5043641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turner        sigaction(SIGABRT, &act, NULL);
5053641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turner    }
5063641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turner#endif
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    abort();
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
5110e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerstatic RAMBlock *qemu_get_ram_block(ram_addr_t addr)
5120e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner{
5130e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    RAMBlock *block;
5140e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
5150e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    /* The list is protected by the iothread lock here.  */
5160e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    block = ram_list.mru_block;
5170e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (block && addr - block->offset < block->length) {
5180e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        goto found;
5190e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
5200e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
5210e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (addr - block->offset < block->length) {
5220e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            goto found;
5230e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
5240e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
5250e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
5260e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
5270e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    abort();
5280e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
5290e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerfound:
5300e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    ram_list.mru_block = block;
5310e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    return block;
5320e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Note: start and end must be within the same ram block.  */
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                     int dirty_flags)
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long length, start1;
539280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    int i;
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    start &= TARGET_PAGE_MASK;
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    end = TARGET_PAGE_ALIGN(end);
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    length = end - start;
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (length == 0)
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
547280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    cpu_physical_memory_mask_dirty_range(start, length, dirty_flags);
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we modify the TLB cache so that the dirty bit will be set again
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       when accessing the range */
551280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    start1 = (unsigned long)qemu_safe_ram_ptr(start);
5525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Chek that we don't span multiple blocks - this breaks the
5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner       address comparisons below.  */
554280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
5555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            != (end - 1) - start) {
5565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        abort();
5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5596657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPUState *cpu;
5606657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPU_FOREACH(cpu) {
5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int mmu_idx;
5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
5636657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner            for(i = 0; i < CPU_TLB_SIZE; i++) {
5646657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner                CPUArchState* env = cpu->env_ptr;
5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                      start1, length);
5676657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner            }
5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint cpu_physical_memory_set_dirty_tracking(int enable)
5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    in_migration = enable;
5755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (kvm_enabled()) {
5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return kvm_set_migration_log(enable);
5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
5795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint cpu_physical_memory_get_dirty_tracking(void)
5825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return in_migration;
5845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
586bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerint cpu_physical_sync_dirty_bitmap(hwaddr start_addr,
587bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner                                   hwaddr end_addr)
5885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret = 0;
5905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (kvm_enabled())
5925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
5935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
5945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ram_addr_t ram_addr;
5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *p;
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
6025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
6035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            + tlb_entry->addend);
604280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        ram_addr = qemu_ram_addr_from_host_nofail(p);
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!cpu_physical_memory_is_dirty(ram_addr)) {
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tlb_entry->addr_write |= TLB_NOTDIRTY;
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* update the TLB according to the current state of the dirty bits */
6124d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnervoid cpu_tlb_update_dirty(CPUArchState *env)
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
6155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int mmu_idx;
6165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        for(i = 0; i < CPU_TLB_SIZE; i++)
6185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6254d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnervoid tlb_flush(CPUArchState *env, int flush_global)
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6294d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnervoid tlb_flush_page(CPUArchState *env, target_ulong addr)
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6334d6613c972c53178ff9ea39de7fa79d07649fad5David 'Digit' Turnerint tlb_set_page_exec(CPUArchState *env, target_ulong vaddr,
634bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner                      hwaddr paddr, int prot,
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      int mmu_idx, int is_softmmu)
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
640e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic inline void tlb_set_dirty(CPUOldState *env,
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 unsigned long addr, target_ulong vaddr)
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* defined(CONFIG_USER_ONLY) */
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             ram_addr_t memory, ram_addr_t region_offset);
650bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void *subpage_init (hwaddr base, ram_addr_t *phys,
6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                           ram_addr_t orig_memory, ram_addr_t region_offset);
6520e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
6530e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerstatic void *(*phys_mem_alloc)(size_t size) = qemu_anon_ram_alloc;
6540e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
6550e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner/*
6560e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner * Set a custom physical guest memory alloator.
6570e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner * Accelerators with unusual needs may need this.  Hopefully, we can
6580e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner * get rid of it eventually.
6590e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner */
6600e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnervoid phys_mem_set_alloc(void *(*alloc)(size_t))
6610e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner{
6620e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    phys_mem_alloc = alloc;
6630e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
6640e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      need_subpage)                                     \
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do {                                                                \
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (addr > start_addr)                                          \
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            start_addr2 = 0;                                            \
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {                                                          \
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            start_addr2 = start_addr & ~TARGET_PAGE_MASK;               \
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (start_addr2 > 0)                                        \
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                need_subpage = 1;                                       \
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }                                                               \
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                                                        \
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE)        \
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            end_addr2 = TARGET_PAGE_SIZE - 1;                           \
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {                                                          \
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (end_addr2 < TARGET_PAGE_SIZE - 1)                       \
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                need_subpage = 1;                                       \
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }                                                               \
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (0)
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
685a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner/* register physical memory.
686a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   For RAM, 'size' must be a multiple of the target page size.
687a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   io memory page.  The address used when calling the IO function is
6895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   the offset from the start of the region, plus region_offset.  Both
6905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   start_addr and region_offset are rounded down to a page boundary
6915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   before calculating this offset.  This should not be a problem unless
6925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   the low bits of start_addr and region_offset differ.  */
693bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnervoid cpu_register_physical_memory_log(hwaddr start_addr,
6945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                         ram_addr_t size,
6955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                         ram_addr_t phys_offset,
696280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                                         ram_addr_t region_offset,
697280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                                         bool log_dirty)
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
699bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner    hwaddr addr, end_addr;
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PhysPageDesc *p;
7016657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPUState *cpu;
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ram_addr_t orig_size = size;
703280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    subpage_t *subpage;
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (kvm_enabled())
7065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        kvm_set_phys_mem(start_addr, size, phys_offset);
707a381ef07088ce479610129e37bfef42538f397daJun Nakajima#ifdef CONFIG_HAX
708a381ef07088ce479610129e37bfef42538f397daJun Nakajima    if (hax_enabled())
709a381ef07088ce479610129e37bfef42538f397daJun Nakajima        hax_set_phys_mem(start_addr, size, phys_offset);
710a381ef07088ce479610129e37bfef42538f397daJun Nakajima#endif
7115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (phys_offset == IO_MEM_UNASSIGNED) {
7135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        region_offset = start_addr;
7145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    region_offset &= TARGET_PAGE_MASK;
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
717bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner    end_addr = start_addr + (hwaddr)size;
718280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
719280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    addr = start_addr;
720280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    do {
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = phys_page_find(addr >> TARGET_PAGE_BITS);
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ram_addr_t orig_memory = p->phys_offset;
724bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner            hwaddr start_addr2, end_addr2;
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int need_subpage = 0;
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          need_subpage);
729280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            if (need_subpage) {
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (!(orig_memory & IO_MEM_SUBPAGE)) {
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
7325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                           &p->phys_offset, orig_memory,
7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                           p->region_offset);
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                            >> IO_MEM_SHIFT];
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
7385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                subpage_register(subpage, start_addr2, end_addr2, phys_offset,
7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 region_offset);
7405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                p->region_offset = 0;
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p->phys_offset = phys_offset;
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    (phys_offset & IO_MEM_ROMD))
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    phys_offset += TARGET_PAGE_SIZE;
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p->phys_offset = phys_offset;
7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            p->region_offset = region_offset;
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                (phys_offset & IO_MEM_ROMD)) {
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                phys_offset += TARGET_PAGE_SIZE;
7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
755bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner                hwaddr start_addr2, end_addr2;
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int need_subpage = 0;
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              end_addr2, need_subpage);
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
761280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                if (need_subpage) {
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
7635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                           &p->phys_offset, IO_MEM_UNASSIGNED,
7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                           addr & TARGET_PAGE_MASK);
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    subpage_register(subpage, start_addr2, end_addr2,
7665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                     phys_offset, region_offset);
7675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    p->region_offset = 0;
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        region_offset += TARGET_PAGE_SIZE;
772280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        addr += TARGET_PAGE_SIZE;
773280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    } while (addr != end_addr);
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* since each CPU stores ram addresses in its TLB cache, we must
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       reset the modified entries */
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: slow ! */
7786657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner    CPU_FOREACH(cpu) {
7796657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner        tlb_flush(cpu->env_ptr, 1);
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: temporary until new memory mapping API */
784bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerram_addr_t cpu_get_physical_page_desc(hwaddr addr)
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PhysPageDesc *p;
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = phys_page_find(addr >> TARGET_PAGE_BITS);
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p)
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return IO_MEM_UNASSIGNED;
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return p->phys_offset;
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
794bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnervoid qemu_register_coalesced_mmio(hwaddr addr, ram_addr_t size)
7955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (kvm_enabled())
7975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        kvm_coalesce_mmio_region(addr, size);
7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
800bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnervoid qemu_unregister_coalesced_mmio(hwaddr addr, ram_addr_t size)
8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (kvm_enabled())
8035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        kvm_uncoalesce_mmio_region(addr, size);
8045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8060e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnervoid qemu_mutex_lock_ramlist(void)
8070e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner{
8080e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    qemu_mutex_lock(&ram_list.mutex);
8090e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
8100e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8110e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnervoid qemu_mutex_unlock_ramlist(void)
8120e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner{
8130e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    qemu_mutex_unlock(&ram_list.mutex);
8140e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
8150e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8160e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#if defined(__linux__) && !defined(CONFIG_ANDROID)
8170e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8180e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#include <sys/vfs.h>
8190e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8200e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#define HUGETLBFS_MAGIC       0x958458f6
8210e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8220e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerstatic long gethugepagesize(const char *path)
8230e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner{
8240e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    struct statfs fs;
8250e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    int ret;
8260e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8270e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    do {
8280e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        ret = statfs(path, &fs);
8290e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    } while (ret != 0 && errno == EINTR);
8300e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8310e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (ret != 0) {
8320e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        perror(path);
8330e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        return 0;
8340e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
8350e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8360e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (fs.f_type != HUGETLBFS_MAGIC)
8370e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        fprintf(stderr, "Warning: path not on HugeTLBFS: %s\n", path);
8380e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8390e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    return fs.f_bsize;
8400e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
8410e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8420e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerstatic sigjmp_buf sigjump;
8430e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8440e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerstatic void sigbus_handler(int signal)
8450e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner{
8460e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    siglongjmp(sigjump, 1);
8470e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
8480e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8490e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerstatic void *file_ram_alloc(RAMBlock *block,
8500e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                            ram_addr_t memory,
8510e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                            const char *path)
8520e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner{
8530e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    char *filename;
8540e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    char *sanitized_name;
8550e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    char *c;
8560e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    void *area;
8570e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    int fd;
8580e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    unsigned long hpagesize;
8590e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8600e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    hpagesize = gethugepagesize(path);
8610e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (!hpagesize) {
8620e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        return NULL;
8630e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
8640e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8650e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (memory < hpagesize) {
8660e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        return NULL;
8670e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
8680e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8690e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (kvm_enabled() && !kvm_has_sync_mmu()) {
8700e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        fprintf(stderr, "host lacks kvm mmu notifiers, -mem-path unsupported\n");
8710e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        return NULL;
8720e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
8730e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8740e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    /* Make name safe to use with mkstemp by replacing '/' with '_'. */
8750e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    sanitized_name = g_strdup(block->mr->name);
8760e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    for (c = sanitized_name; *c != '\0'; c++) {
8770e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (*c == '/')
8780e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            *c = '_';
8790e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
8800e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8810e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    filename = g_strdup_printf("%s/qemu_back_mem.%s.XXXXXX", path,
8820e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                               sanitized_name);
8830e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    g_free(sanitized_name);
8840e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8850e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    fd = mkstemp(filename);
8860e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (fd < 0) {
8870e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        perror("unable to create backing store for hugepages");
8880e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        g_free(filename);
8890e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        return NULL;
8900e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
8910e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    unlink(filename);
8920e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    g_free(filename);
8930e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8940e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    memory = (memory+hpagesize-1) & ~(hpagesize-1);
8950e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
8960e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    /*
8970e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner     * ftruncate is not supported by hugetlbfs in older
8980e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner     * hosts, so don't bother bailing out on errors.
8990e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner     * If anything goes wrong with it under other filesystems,
9000e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner     * mmap will fail.
9010e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner     */
9020e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (ftruncate(fd, memory))
9030e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        perror("ftruncate");
9040e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
9050e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    area = mmap(0, memory, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
9060e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (area == MAP_FAILED) {
9070e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        perror("file_ram_alloc: can't mmap RAM pages");
9080e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        close(fd);
9090e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        return (NULL);
9100e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
9110e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
9120e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (mem_prealloc) {
9130e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        int ret, i;
9140e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        struct sigaction act, oldact;
9150e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        sigset_t set, oldset;
9160e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
9170e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        memset(&act, 0, sizeof(act));
9180e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        act.sa_handler = &sigbus_handler;
9190e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        act.sa_flags = 0;
9200e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
9210e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        ret = sigaction(SIGBUS, &act, &oldact);
9220e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (ret) {
9230e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            perror("file_ram_alloc: failed to install signal handler");
9240e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            exit(1);
9250e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
9260e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
9270e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        /* unblock SIGBUS */
9280e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        sigemptyset(&set);
9290e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        sigaddset(&set, SIGBUS);
9300e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
9310e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
9320e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (sigsetjmp(sigjump, 1)) {
9330e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            fprintf(stderr, "file_ram_alloc: failed to preallocate pages\n");
9340e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            exit(1);
9350e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
9360e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
9370e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        /* MAP_POPULATE silently ignores failures */
9380e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        for (i = 0; i < (memory/hpagesize)-1; i++) {
9390e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            memset(area + (hpagesize*i), 0, 1);
9400e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
9410e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
9420e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        ret = sigaction(SIGBUS, &oldact, NULL);
9430e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (ret) {
9440e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            perror("file_ram_alloc: failed to reinstall signal handler");
9450e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            exit(1);
9460e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
9470e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
9480e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        pthread_sigmask(SIG_SETMASK, &oldset, NULL);
9490e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
9500e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
9510e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    block->fd = fd;
9520e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    return area;
9530e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
9540e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#else
9550e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerstatic void *file_ram_alloc(RAMBlock *block,
9560e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                            ram_addr_t memory,
9570e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                            const char *path)
9580e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner{
9590e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    fprintf(stderr, "-mem-path not supported on this host\n");
9600e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    exit(1);
9610e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
9620e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#endif
9630e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
964280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turnerstatic ram_addr_t find_ram_offset(ram_addr_t size)
9655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
966280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    RAMBlock *block, *next_block;
9670e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX;
9680e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
9690e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    assert(size != 0); /* it would hand out same offset multiple times */
970280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
9710e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (QTAILQ_EMPTY(&ram_list.blocks))
972280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        return 0;
973280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
9740e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
9750e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        ram_addr_t end, next = RAM_ADDR_MAX;
976280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
977280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        end = block->offset + block->length;
978280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
9790e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        QTAILQ_FOREACH(next_block, &ram_list.blocks, next) {
980280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            if (next_block->offset >= end) {
981280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                next = MIN(next, next_block->offset);
982280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            }
983280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        }
984280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        if (next - end >= size && next - end < mingap) {
9850e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            offset = end;
986280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            mingap = next - end;
987280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        }
988280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    }
9890e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
9900e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (offset == RAM_ADDR_MAX) {
9910e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        fprintf(stderr, "Failed to find gap of requested size: %" PRIu64 "\n",
9920e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                (uint64_t)size);
9930e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        abort();
9940e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
9950e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
996280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    return offset;
997280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner}
998280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
9990e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerram_addr_t last_ram_offset(void)
1000280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner{
1001280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    RAMBlock *block;
1002280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    ram_addr_t last = 0;
1003280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
10040e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    QTAILQ_FOREACH(block, &ram_list.blocks, next)
1005280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        last = MAX(last, block->offset + block->length);
1006280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
1007280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    return last;
1008280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner}
1009280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
10100e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerstatic void qemu_ram_setup_dump(void *addr, ram_addr_t size)
10110e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner{
10120e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#ifndef CONFIG_ANDROID
10130e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    int ret;
10140e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
10150e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */
10160e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (!qemu_opt_get_bool(qemu_get_machine_opts(),
10170e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                           "dump-guest-core", true)) {
10180e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP);
10190e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (ret) {
10200e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            perror("qemu_madvise");
10210e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            fprintf(stderr, "madvise doesn't support MADV_DONTDUMP, "
10220e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                            "but dump_guest_core=off specified\n");
10230e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
10240e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
10250e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#endif  // !CONFIG_ANDROID
10260e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
10270e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
10280e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnervoid qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
1029280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner{
1030280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    RAMBlock *new_block, *block;
10315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10320e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    new_block = NULL;
10330e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
10340e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (block->offset == addr) {
10350e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            new_block = block;
10360e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            break;
10370e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
10380e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
10390e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    assert(new_block);
10400e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    assert(!new_block->idstr[0]);
10415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10420e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (dev) {
10430e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        char *id = qdev_get_dev_path(dev);
1044280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        if (id) {
1045280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
1046aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner            g_free(id);
1047280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        }
1048280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    }
1049280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
1050280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
10510e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    /* This assumes the iothread lock is taken here too.  */
10520e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    qemu_mutex_lock_ramlist();
10530e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
10540e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (block != new_block && !strcmp(block->idstr, new_block->idstr)) {
1055280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
1056280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                    new_block->idstr);
1057280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            abort();
1058280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        }
1059280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    }
10600e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    qemu_mutex_unlock_ramlist();
10610e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
10620e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
10630e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerstatic int memory_try_enable_merging(void *addr, size_t len)
10640e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner{
10650e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#ifndef CONFIG_ANDROID
10660e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (!qemu_opt_get_bool(qemu_get_machine_opts(), "mem-merge", true)) {
10670e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        /* disabled by the user */
10680e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        return 0;
10690e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
10700e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
10710e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE);
10720e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#else  // CONFIG_ANDROID
10730e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE);
10740e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#endif  // CONFIG_ANDROID
10750e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
10760e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
10770e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
10780e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                                   ram_addr_t size, void *host)
10790e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner{
10800e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    RAMBlock *block, *new_block;
1081280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
10820e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    size = TARGET_PAGE_ALIGN(size);
10830e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    new_block = g_malloc0(sizeof(*new_block));
10840e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    new_block->fd = -1;
10850e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
10860e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    /* This assumes the iothread lock is taken here too.  */
10870e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    qemu_mutex_lock_ramlist();
10880e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    //new_block->mr = mr;
10890e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    new_block->offset = find_ram_offset(size);
1090280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    if (host) {
1091280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        new_block->host = host;
1092280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        new_block->flags |= RAM_PREALLOC_MASK;
10930e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    } else if (xen_enabled()) {
1094280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        if (mem_path) {
10950e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            fprintf(stderr, "-mem-path not supported with Xen\n");
1096280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            exit(1);
10970e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
10980e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        //xen_ram_alloc(new_block->offset, size, mr);
10990e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    } else {
11000e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (mem_path) {
11010e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            if (phys_mem_alloc != qemu_anon_ram_alloc) {
11020e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                /*
11030e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                 * file_ram_alloc() needs to allocate just like
11040e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                 * phys_mem_alloc, but we haven't bothered to provide
11050e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                 * a hook there.
11060e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                 */
11070e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                fprintf(stderr,
11080e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                        "-mem-path not supported with this accelerator\n");
11090e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                exit(1);
1110a381ef07088ce479610129e37bfef42538f397daJun Nakajima            }
11110e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            new_block->host = file_ram_alloc(new_block, size, mem_path);
1112a381ef07088ce479610129e37bfef42538f397daJun Nakajima        }
11130e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (!new_block->host) {
11140e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            new_block->host = phys_mem_alloc(size);
11150e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            if (!new_block->host) {
11160e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                fprintf(stderr, "Cannot set up guest memory '%s': %s\n",
11170e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                        name, strerror(errno));
11180e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                exit(1);
11190e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            }
1120f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner#ifdef CONFIG_HAX
1121f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner            if (hax_enabled()) {
1122f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                /*
1123f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                 * In HAX, qemu allocates the virtual address, and HAX kernel
1124f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                 * module populates the region with physical memory. Currently
1125f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                 * we don’t populate guest memory on demand, thus we should
1126f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                 * make sure that sufficient amount of memory is available in
1127f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                 * advance.
1128f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                 */
1129f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                int ret = hax_populate_ram(
1130f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                        (uint64_t)(uintptr_t)new_block->host,
1131f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                        (uint32_t)size);
1132f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                if (ret < 0) {
1133f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                    fprintf(stderr, "Hax failed to populate ram\n");
1134f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                    exit(-1);
1135f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner                }
1136f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner            }
1137f2de2ae9ce153cea6119b05e640dbf35db3b519aDavid 'Digit' Turner#endif  // CONFIG_HAX
11380e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            memory_try_enable_merging(new_block->host, size);
1139280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        }
1140280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    }
11415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    new_block->length = size;
11425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1143454cb8340615211d248bbc3ac380049cced90760David 'Digit' Turner    if (dev) {
1144454cb8340615211d248bbc3ac380049cced90760David 'Digit' Turner        char *id = qdev_get_dev_path(dev);
1145454cb8340615211d248bbc3ac380049cced90760David 'Digit' Turner        if (id) {
1146454cb8340615211d248bbc3ac380049cced90760David 'Digit' Turner            snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
1147454cb8340615211d248bbc3ac380049cced90760David 'Digit' Turner            g_free(id);
1148454cb8340615211d248bbc3ac380049cced90760David 'Digit' Turner        }
1149454cb8340615211d248bbc3ac380049cced90760David 'Digit' Turner    }
1150454cb8340615211d248bbc3ac380049cced90760David 'Digit' Turner    pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
1151454cb8340615211d248bbc3ac380049cced90760David 'Digit' Turner
11520e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    /* Keep the list sorted from biggest to smallest block.  */
11530e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
11540e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (block->length < new_block->length) {
11550e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            break;
11560e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
11570e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
11580e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (block) {
11590e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        QTAILQ_INSERT_BEFORE(block, new_block, next);
11600e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    } else {
11610e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        QTAILQ_INSERT_TAIL(&ram_list.blocks, new_block, next);
11620e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
11630e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    ram_list.mru_block = NULL;
11640e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
11650e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    ram_list.version++;
11660e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    qemu_mutex_unlock_ramlist();
11675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1168aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
1169280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                                       last_ram_offset() >> TARGET_PAGE_BITS);
1170280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
11715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner           0xff, size >> TARGET_PAGE_BITS);
11720e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    //cpu_physical_memory_set_dirty_range(new_block->offset, size, 0xff);
11735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11747891dd35fa2439a70f43ab8572778a398365bf24David 'Digit' Turner    qemu_ram_setup_dump(new_block->host, size);
11750e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    //qemu_madvise(new_block->host, size, QEMU_MADV_HUGEPAGE);
11760e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    //qemu_madvise(new_block->host, size, QEMU_MADV_DONTFORK);
1177454cb8340615211d248bbc3ac380049cced90760David 'Digit' Turner
11785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (kvm_enabled())
11795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        kvm_setup_guest_memory(new_block->host, size);
11805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return new_block->offset;
11825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1184280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turnerram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
1185280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner{
1186280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    return qemu_ram_alloc_from_ptr(dev, name, size, NULL);
1187280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner}
1188280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
11890e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnervoid qemu_ram_free_from_ptr(ram_addr_t addr)
11900e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner{
11910e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    RAMBlock *block;
11920e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
11930e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    /* This assumes the iothread lock is taken here too.  */
11940e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    qemu_mutex_lock_ramlist();
11950e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
11960e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (addr == block->offset) {
11970e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            QTAILQ_REMOVE(&ram_list.blocks, block, next);
11980e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            ram_list.mru_block = NULL;
11990e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            ram_list.version++;
12000e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            g_free(block);
12010e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            break;
12020e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
12030e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
12040e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    qemu_mutex_unlock_ramlist();
12050e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
12060e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid qemu_ram_free(ram_addr_t addr)
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1209280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    RAMBlock *block;
1210280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
12110e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    /* This assumes the iothread lock is taken here too.  */
12120e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    qemu_mutex_lock_ramlist();
12130e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1214280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        if (addr == block->offset) {
12150e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            QTAILQ_REMOVE(&ram_list.blocks, block, next);
12160e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            ram_list.mru_block = NULL;
12170e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            ram_list.version++;
1218280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            if (block->flags & RAM_PREALLOC_MASK) {
1219280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                ;
12200e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            } else if (xen_enabled()) {
12210e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                //xen_invalidate_map_cache_entry(block->host);
12220e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#ifndef _WIN32
12230e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            } else if (block->fd >= 0) {
1224280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                munmap(block->host, block->length);
12250e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                close(block->fd);
1226280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner#endif
12270e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            } else {
12280e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                qemu_anon_ram_free(block->host, block->length);
1229280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            }
1230aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner            g_free(block);
12310e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            break;
1232280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        }
1233280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    }
12340e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    qemu_mutex_unlock_ramlist();
1235280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
1236280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner}
1237280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
1238280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner#ifndef _WIN32
1239280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turnervoid qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
1240280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner{
1241280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    RAMBlock *block;
1242280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    ram_addr_t offset;
1243280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    int flags;
1244280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    void *area, *vaddr;
1245280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
12460e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1247280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        offset = addr - block->offset;
1248280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        if (offset < block->length) {
1249280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            vaddr = block->host + offset;
1250280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            if (block->flags & RAM_PREALLOC_MASK) {
1251280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                ;
12520e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            } else if (xen_enabled()) {
12530e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                abort();
1254280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            } else {
1255280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                flags = MAP_FIXED;
1256280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                munmap(vaddr, length);
12570e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                if (block->fd >= 0) {
1258280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner#ifdef MAP_POPULATE
12590e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                    flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
12600e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                        MAP_PRIVATE;
1261280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner#else
12620e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                    flags |= MAP_PRIVATE;
1263280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner#endif
12640e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                    area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
12650e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                                flags, block->fd, offset);
1266280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                } else {
12670e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                    /*
12680e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                     * Remap needs to match alloc.  Accelerators that
12690e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                     * set phys_mem_alloc never remap.  If they did,
12700e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                     * we'd need a remap hook here.
12710e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                     */
12720e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                    assert(phys_mem_alloc == qemu_anon_ram_alloc);
12730e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
1274280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                    flags |= MAP_PRIVATE | MAP_ANONYMOUS;
1275280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                    area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
1276280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                                flags, -1, 0);
1277280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                }
1278280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                if (area != vaddr) {
12790e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                    fprintf(stderr, "Could not remap addr: "
12800e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                            RAM_ADDR_FMT "@" RAM_ADDR_FMT "\n",
1281280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                            length, addr);
1282280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                    exit(1);
1283280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                }
12840e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                memory_try_enable_merging(vaddr, length);
12850e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                qemu_ram_setup_dump(vaddr, length);
1286280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            }
1287280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            return;
1288280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        }
1289280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    }
12905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1291280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner#endif /* !_WIN32 */
12925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Return a host pointer to ram allocated with qemu_ram_alloc.
12945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   With the exception of the softmmu code in this file, this should
12955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   only be used for local memory (e.g. video ram) that the device owns,
12965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   and knows it isn't going to access beyond the end of the block.
12975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   It should not be used for general purpose DMA.
12995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
13005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
13015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid *qemu_get_ram_ptr(ram_addr_t addr)
13025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13030e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    RAMBlock *block = qemu_get_ram_block(addr);
13040e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#if 0
13050e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (xen_enabled()) {
13060e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        /* We need to check if the requested address is in the RAM
13070e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner         * because we don't want to map the entire memory in QEMU.
13080e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner         * In that case just map until the end of the page.
13090e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner         */
13100e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (block->offset == 0) {
13110e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            return xen_map_cache(addr, 0, 0);
13120e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        } else if (block->host == NULL) {
13130e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            block->host =
13140e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner                xen_map_cache(block->offset, block->length, 1);
1315280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        }
1316280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    }
13170e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#endif
13180e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    return block->host + (addr - block->offset);
13190e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner}
1320280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
1321280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner/* Return a host pointer to ram allocated with qemu_ram_alloc.
1322280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner * Same as qemu_get_ram_ptr but avoid reordering ramblocks.
1323280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner */
1324280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turnervoid *qemu_safe_ram_ptr(ram_addr_t addr)
1325280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner{
1326280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    RAMBlock *block;
1327280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
13280e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1329280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        if (addr - block->offset < block->length) {
13300e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            return block->host + (addr - block->offset);
13310e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
1332280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    }
13335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1334280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
1335280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    abort();
1336280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
1337280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    return NULL;
1338280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner}
1339280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
13400e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner/* Some of the softmmu routines need to translate from a host pointer
13410e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner   (typically a TLB entry) back to a ram offset.  */
1342280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turnerint qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
13435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    RAMBlock *block;
13455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t *host = ptr;
13460e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#if 0
13470e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (xen_enabled()) {
13480e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        *ram_addr = xen_ram_addr_from_mapcache(ptr);
13490e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        return qemu_get_ram_block(*ram_addr)->mr;
13500e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
13510e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner#endif
13520e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    block = ram_list.mru_block;
13530e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    if (block && block->host && host - block->host < block->length) {
13540e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        goto found;
13550e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    }
13565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13570e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
13580e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        /* This case append when the block is not mapped. */
13590e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        if (block->host == NULL) {
13600e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            continue;
13610e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
1362280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        if (host - block->host < block->length) {
13630e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner            goto found;
13640e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner        }
1365280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    }
13660e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
1367280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    return -1;
13680e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner
13690e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turnerfound:
13700e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    *ram_addr = block->offset + (host - block->host);
13710e8e7484a282d510c335a5f8a238ad02250345adDavid 'Digit' Turner    return 0;
1372280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner}
1373280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
1374280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner/* Some of the softmmu routines need to translate from a host pointer
1375280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner   (typically a TLB entry) back to a ram offset.  */
1376280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turnerram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
1377280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner{
1378280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    ram_addr_t ram_addr;
1379280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner
1380280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
13815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "Bad ram pointer %p\n", ptr);
13825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        abort();
13835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
1384280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    return ram_addr;
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1387bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t unassigned_mem_readb(void *opaque, hwaddr addr)
13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_UNASSIGNED
13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1392a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
13936cf763a179bb432ef845025bb3639fcaf1251bd0David 'Digit' Turner    cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 1);
13945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
13955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
13965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1398bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t unassigned_mem_readw(void *opaque, hwaddr addr)
13995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef DEBUG_UNASSIGNED
14015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
14025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
1403a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
14046cf763a179bb432ef845025bb3639fcaf1251bd0David 'Digit' Turner    cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 2);
14055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
14065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
14075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1409bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t unassigned_mem_readl(void *opaque, hwaddr addr)
14105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef DEBUG_UNASSIGNED
14125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
14135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
1414a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
14156cf763a179bb432ef845025bb3639fcaf1251bd0David 'Digit' Turner    cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, 4);
14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
14188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1420bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void unassigned_mem_writeb(void *opaque, hwaddr addr, uint32_t val)
14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_UNASSIGNED
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1425a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
14266cf763a179bb432ef845025bb3639fcaf1251bd0David 'Digit' Turner    cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 1);
14275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
14285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1430bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void unassigned_mem_writew(void *opaque, hwaddr addr, uint32_t val)
14315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef DEBUG_UNASSIGNED
14335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
14345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
1435a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
14366cf763a179bb432ef845025bb3639fcaf1251bd0David 'Digit' Turner    cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 2);
14375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
14385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1440bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void unassigned_mem_writel(void *opaque, hwaddr addr, uint32_t val)
14415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef DEBUG_UNASSIGNED
14435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
14445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
1445a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
14466cf763a179bb432ef845025bb3639fcaf1251bd0David 'Digit' Turner    cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, 4);
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14503641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turnerstatic CPUReadMemoryFunc * const unassigned_mem_read[3] = {
14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unassigned_mem_readb,
14525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unassigned_mem_readw,
14535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unassigned_mem_readl,
14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14563641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turnerstatic CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
14578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unassigned_mem_writeb,
14585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unassigned_mem_writew,
14595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unassigned_mem_writel,
14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1462bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void notdirty_mem_writeb(void *opaque, hwaddr ram_addr,
14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                uint32_t val)
14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int dirty_flags;
1466280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
1469ff9a2b851f95dff46171881afcdc65b2e164d36dDavid 'Digit' Turner        tb_invalidate_phys_page_fast0(ram_addr, 1);
1470280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    stb_p(qemu_get_ram_ptr(ram_addr), val);
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
1475280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we remove the notdirty callback only if the code has been
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       flushed */
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dirty_flags == 0xff)
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1482bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void notdirty_mem_writew(void *opaque, hwaddr ram_addr,
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                uint32_t val)
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int dirty_flags;
1486280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
1489ff9a2b851f95dff46171881afcdc65b2e164d36dDavid 'Digit' Turner        tb_invalidate_phys_page_fast0(ram_addr, 2);
1490280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    stw_p(qemu_get_ram_ptr(ram_addr), val);
14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
1495280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we remove the notdirty callback only if the code has been
14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       flushed */
14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dirty_flags == 0xff)
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1502bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void notdirty_mem_writel(void *opaque, hwaddr ram_addr,
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                uint32_t val)
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int dirty_flags;
1506280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
1509ff9a2b851f95dff46171881afcdc65b2e164d36dDavid 'Digit' Turner        tb_invalidate_phys_page_fast0(ram_addr, 4);
1510280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner        dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    stl_p(qemu_get_ram_ptr(ram_addr), val);
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
1515280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we remove the notdirty callback only if the code has been
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       flushed */
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dirty_flags == 0xff)
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15223641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turnerstatic CPUReadMemoryFunc * const error_mem_read[3] = {
15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, /* never used */
15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, /* never used */
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, /* never used */
15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15283641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turnerstatic CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    notdirty_mem_writeb,
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    notdirty_mem_writew,
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    notdirty_mem_writel,
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15348b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turnerstatic void tb_check_watchpoint(CPUArchState* env)
15358b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner{
15368b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner    TranslationBlock *tb = tb_find_pc(env->mem_io_pc);
15378b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner    if (!tb) {
15388b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner        cpu_abort(env, "check_watchpoint: could not find TB for "
15398b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner                  "pc=%p", (void *)env->mem_io_pc);
15408b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner    }
15418b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner    cpu_restore_state(env, env->mem_io_pc);
15428b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner    tb_phys_invalidate(tb, -1);
15438b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner}
15448b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner
15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Generate a debug exception if a watchpoint has been hit.  */
15465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void check_watchpoint(int offset, int len_mask, int flags)
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1548bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner    CPUState *cpu = current_cpu;
1549bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner    CPUArchState *env = cpu->env_ptr;
15505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    target_ulong pc, cs_base;
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong vaddr;
15525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUWatchpoint *wp;
15535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int cpu_flags;
15545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (env->watchpoint_hit) {
15565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* We re-entered the check after replacing the TB. Now raise
15575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * the debug interrupt so that is will trigger after the
15585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * current instruction. */
1559bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner        cpu_interrupt(cpu, CPU_INTERRUPT_DEBUG);
15605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
15615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
1563a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
15645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if ((vaddr == (wp->vaddr & len_mask) ||
15655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner             (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
15665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            wp->flags |= BP_WATCHPOINT_HIT;
15675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (!env->watchpoint_hit) {
15685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                env->watchpoint_hit = wp;
15698b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner                tb_check_watchpoint(env);
15705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (wp->flags & BP_STOP_BEFORE_ACCESS) {
15715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    env->exception_index = EXCP_DEBUG;
157285c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner                    cpu_loop_exit(env);
15735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else {
15745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
15755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tb_gen_code(env, pc, cs_base, cpu_flags, 1);
157685c62200dbdb7ced04b34cb228098b888a8cd828David 'Digit' Turner                    cpu_resume_from_signal(env, NULL);
15775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
15785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
15795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
15805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            wp->flags &= ~BP_WATCHPOINT_HIT;
15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Watchpoint access routines.  Watchpoints are inserted using TLB tricks,
15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   so these check for a hit then pass through to the normal out-of-line
15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   phys routines.  */
1588bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t watch_mem_readb(void *opaque, hwaddr addr)
15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ldub_phys(addr);
15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1594bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t watch_mem_readw(void *opaque, hwaddr addr)
15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return lduw_phys(addr);
15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1600bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t watch_mem_readl(void *opaque, hwaddr addr)
16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ldl_phys(addr);
16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1606bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void watch_mem_writeb(void *opaque, hwaddr addr,
16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             uint32_t val)
16088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stb_phys(addr, val);
16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1613bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void watch_mem_writew(void *opaque, hwaddr addr,
16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             uint32_t val)
16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stw_phys(addr, val);
16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1620bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void watch_mem_writel(void *opaque, hwaddr addr,
16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             uint32_t val)
16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stl_phys(addr, val);
16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16273641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turnerstatic CPUReadMemoryFunc * const watch_mem_read[3] = {
16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    watch_mem_readb,
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    watch_mem_readw,
16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    watch_mem_readl,
16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16333641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turnerstatic CPUWriteMemoryFunc * const watch_mem_write[3] = {
16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    watch_mem_writeb,
16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    watch_mem_writew,
16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    watch_mem_writel,
16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
16388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1639bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic inline uint32_t subpage_readlen (subpage_t *mmio, hwaddr addr,
16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 unsigned int len)
16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t ret;
16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int idx;
16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    idx = SUBPAGE_IDX(addr);
16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SUBPAGE)
16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           mmio, len, addr, idx);
16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
16515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                       addr + mmio->region_offset[idx][0][len]);
16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1656bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic inline void subpage_writelen (subpage_t *mmio, hwaddr addr,
16578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              uint32_t value, unsigned int len)
16588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int idx;
16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    idx = SUBPAGE_IDX(addr);
16628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SUBPAGE)
16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           mmio, len, addr, idx, value);
16658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
16675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                  addr + mmio->region_offset[idx][1][len],
16685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                  value);
16698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1671bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t subpage_readb (void *opaque, hwaddr addr)
16728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SUBPAGE)
16748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
16758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return subpage_readlen(opaque, addr, 0);
16788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1680bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void subpage_writeb (void *opaque, hwaddr addr,
16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            uint32_t value)
16828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SUBPAGE)
16848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
16858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    subpage_writelen(opaque, addr, value, 0);
16878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1689bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t subpage_readw (void *opaque, hwaddr addr)
16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SUBPAGE)
16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return subpage_readlen(opaque, addr, 1);
16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1698bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void subpage_writew (void *opaque, hwaddr addr,
16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            uint32_t value)
17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SUBPAGE)
17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
17038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
17048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    subpage_writelen(opaque, addr, value, 1);
17058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1707bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t subpage_readl (void *opaque, hwaddr addr)
17088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SUBPAGE)
17108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
17118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
17128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return subpage_readlen(opaque, addr, 2);
17148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void subpage_writel (void *opaque,
1717bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner                         hwaddr addr, uint32_t value)
17188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SUBPAGE)
17208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
17228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    subpage_writelen(opaque, addr, value, 2);
17238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17253641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turnerstatic CPUReadMemoryFunc * const subpage_read[] = {
17268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    &subpage_readb,
17278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    &subpage_readw,
17288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    &subpage_readl,
17298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
17308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17313641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turnerstatic CPUWriteMemoryFunc * const subpage_write[] = {
17328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    &subpage_writeb,
17338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    &subpage_writew,
17348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    &subpage_writel,
17358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
17368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
17385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                             ram_addr_t memory, ram_addr_t region_offset)
17398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int idx, eidx;
17418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int i;
17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    idx = SUBPAGE_IDX(start);
17468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    eidx = SUBPAGE_IDX(end);
17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SUBPAGE)
1748a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
17498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           mmio, start, end, idx, eidx, memory);
17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
17518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memory >>= IO_MEM_SHIFT;
17528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (; idx <= eidx; idx++) {
17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (i = 0; i < 4; i++) {
1754fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner            if (_io_mem_read[memory][i]) {
1755fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner                mmio->mem_read[idx][i] = &_io_mem_read[memory][i];
17568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                mmio->opaque[idx][0][i] = io_mem_opaque[memory];
17575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                mmio->region_offset[idx][0][i] = region_offset;
17588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
1759fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner            if (_io_mem_write[memory][i]) {
1760fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner                mmio->mem_write[idx][i] = &_io_mem_write[memory][i];
17618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                mmio->opaque[idx][1][i] = io_mem_opaque[memory];
17625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                mmio->region_offset[idx][1][i] = region_offset;
17638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
17648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
17688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1770bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void *subpage_init (hwaddr base, ram_addr_t *phys,
17715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                           ram_addr_t orig_memory, ram_addr_t region_offset)
17728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    subpage_t *mmio;
17748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int subpage_memory;
17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1776aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    mmio = g_malloc0(sizeof(subpage_t));
17775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    mmio->base = base;
17795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_SUBPAGE)
17815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
17825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner           mmio, base, TARGET_PAGE_SIZE, subpage_memory);
17838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
17845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    *phys = subpage_memory | IO_MEM_SUBPAGE;
17855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
17865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         region_offset);
17878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return mmio;
17898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int get_free_io_mem_idx(void)
17928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i;
17948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
17965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!io_mem_used[i]) {
17975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            io_mem_used[i] = 1;
17985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return i;
17995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
1800a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
18015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return -1;
18028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* mem_read and mem_write are arrays of functions containing the
18058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   function to access byte (index 0), word (index 1) and dword (index
18065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   2). Functions can be omitted with a NULL function pointer.
18078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   If io_index is non zero, the corresponding io zone is
18088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   modified. If it is zero, a new io zone is allocated. The return
18098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   value can be used with cpu_register_physical_memory(). (-1) is
18108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   returned if error. */
18115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int cpu_register_io_memory_fixed(int io_index,
18123641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turner                                        CPUReadMemoryFunc * const *mem_read,
18133641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turner                                        CPUWriteMemoryFunc * const *mem_write,
18145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                        void *opaque)
18158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i, subwidth = 0;
18178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (io_index <= 0) {
18195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        io_index = get_free_io_mem_idx();
18205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (io_index == -1)
18215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return io_index;
18228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
18235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        io_index >>= IO_MEM_SHIFT;
18248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (io_index >= IO_MEM_NB_ENTRIES)
18258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
18268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i = 0;i < 3; i++) {
18298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!mem_read[i] || !mem_write[i])
18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            subwidth = IO_MEM_SUBWIDTH;
1831fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        _io_mem_read[io_index][i] = mem_read[i];
1832fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        _io_mem_write[io_index][i] = mem_write[i];
18338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    io_mem_opaque[io_index] = opaque;
18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (io_index << IO_MEM_SHIFT) | subwidth;
18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18383641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turnerint cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
18393641106bb6a97e674c767e3805a8b3efa628dc47David 'Digit' Turner                           CPUWriteMemoryFunc * const *mem_write,
18405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                           void *opaque)
18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
18438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid cpu_unregister_io_memory(int io_table_address)
18468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i;
18485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int io_index = io_table_address >> IO_MEM_SHIFT;
18495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (i=0;i < 3; i++) {
1851fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        _io_mem_read[io_index][i] = unassigned_mem_read[i];
1852fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        _io_mem_write[io_index][i] = unassigned_mem_write[i];
18535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
18545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    io_mem_opaque[io_index] = NULL;
18555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    io_mem_used[io_index] = 0;
18565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
18575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void io_mem_init(void)
18595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
18605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i;
18615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
18635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
18645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
18655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (i=0; i<5; i++)
18665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        io_mem_used[i] = 1;
18675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    io_mem_watch = cpu_register_io_memory(watch_mem_read,
18695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                          watch_mem_write, NULL);
18708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !defined(CONFIG_USER_ONLY) */
18738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* physical memory access (slow version, mainly for debug) */
18758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_USER_ONLY)
1876a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turnervoid cpu_physical_memory_rw(hwaddr addr, void *buf,
18778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int len, int is_write)
18788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int l, flags;
18808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong page;
18818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void * p;
18828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (len > 0) {
18848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        page = addr & TARGET_PAGE_MASK;
18858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        l = (page + TARGET_PAGE_SIZE) - addr;
18868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (l > len)
18878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            l = len;
18888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        flags = page_get_flags(page);
18898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(flags & PAGE_VALID))
18908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
18918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (is_write) {
18928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!(flags & PAGE_WRITE))
18938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
18948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* XXX: this code should not depend on lock_user */
18958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
18968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* FIXME - should this return an error rather than just fail? */
18978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
18988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memcpy(p, buf, l);
18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            unlock_user(p, addr, l);
19008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
19018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!(flags & PAGE_READ))
19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
19038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* XXX: this code should not depend on lock_user */
19048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* FIXME - should this return an error rather than just fail? */
19068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
19078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memcpy(buf, p, l);
19088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            unlock_user(p, addr, 0);
19098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len -= l;
19118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += l;
19128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr += l;
19138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1917d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney
1918bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void invalidate_and_set_dirty(hwaddr addr,
1919bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner                                     hwaddr length)
1920d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney{
1921d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney    if (!cpu_physical_memory_is_dirty(addr)) {
1922d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney        /* invalidate code */
1923d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney        tb_invalidate_phys_page_range(addr, addr + length, 0);
1924d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney        /* set dirty bit */
1925d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney        cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG));
1926d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney    }
1927d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney}
1928d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney
1929a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turnervoid cpu_physical_memory_rw(hwaddr addr, void *buf,
19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int len, int is_write)
19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int l, io_index;
19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *ptr;
19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t val;
1935bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner    hwaddr page;
1936b974f3f88682fc47219fe08c308ddc1a07722f4eDavid 'Digit' Turner    ram_addr_t pd;
1937a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner    uint8_t* buf8 = (uint8_t*)buf;
19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PhysPageDesc *p;
19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (len > 0) {
19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        page = addr & TARGET_PAGE_MASK;
19428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        l = (page + TARGET_PAGE_SIZE) - addr;
19438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (l > len)
19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            l = len;
19458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = phys_page_find(page >> TARGET_PAGE_BITS);
19468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!p) {
19478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pd = IO_MEM_UNASSIGNED;
19488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
19498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pd = p->phys_offset;
19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (is_write) {
19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
1954bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner                hwaddr addr1 = addr;
19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
19565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (p)
19575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* XXX: could force cpu_single_env to NULL to avoid
19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   potential bugs */
19605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (l >= 4 && ((addr1 & 3) == 0)) {
19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* 32 bit write access */
1962a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner                    val = ldl_p(buf8);
1963fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner                    io_mem_write(io_index, addr1, val, 4);
19648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    l = 4;
19655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else if (l >= 2 && ((addr1 & 1) == 0)) {
19668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* 16 bit write access */
1967a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner                    val = lduw_p(buf8);
1968fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner                    io_mem_write(io_index, addr1, val, 2);
19698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    l = 2;
19708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
19718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* 8 bit write access */
1972a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner                    val = ldub_p(buf8);
1973fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner                    io_mem_write(io_index, addr1, val, 1);
19748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    l = 1;
19758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
19768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
1977b974f3f88682fc47219fe08c308ddc1a07722f4eDavid 'Digit' Turner                ram_addr_t addr1;
19788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
19798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* RAM case */
19805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ptr = qemu_get_ram_ptr(addr1);
1981a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner                memcpy(ptr, buf8, l);
1982d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney                invalidate_and_set_dirty(addr1, l);
19838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
19848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
19868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                !(pd & IO_MEM_ROMD)) {
1987bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner                hwaddr addr1 = addr;
19888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* I/O case */
19898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
19905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (p)
19915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
19925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (l >= 4 && ((addr1 & 3) == 0)) {
19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* 32 bit read access */
1994fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner                    val = io_mem_read(io_index, addr1, 4);
1995a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner                    stl_p(buf8, val);
19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    l = 4;
19975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else if (l >= 2 && ((addr1 & 1) == 0)) {
19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* 16 bit read access */
1999fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner                    val = io_mem_read(io_index, addr1, 2);
2000a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner                    stw_p(buf8, val);
20018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    l = 2;
20028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
20038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* 8 bit read access */
2004fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner                    val = io_mem_read(io_index, addr1, 1);
2005a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner                    stb_p(buf8, val);
20068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    l = 1;
20078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
20088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
20098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* RAM case */
20105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
20118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    (addr & ~TARGET_PAGE_MASK);
2012a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner                memcpy(buf8, ptr, l);
20138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
20148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len -= l;
2016a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner        buf8 += l;
20178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr += l;
20188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
20198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* used for ROM loading : can write in RAM and ROM */
2022bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnervoid cpu_physical_memory_write_rom(hwaddr addr,
2023a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner                                   const void *buf, int len)
20248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
20258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int l;
20268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *ptr;
2027bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner    hwaddr page;
20288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pd;
2029a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner    const uint8_t* buf8 = (const uint8_t*)buf;
20308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PhysPageDesc *p;
20318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (len > 0) {
20338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        page = addr & TARGET_PAGE_MASK;
20348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        l = (page + TARGET_PAGE_SIZE) - addr;
20358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (l > len)
20368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            l = len;
20378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = phys_page_find(page >> TARGET_PAGE_BITS);
20388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!p) {
20398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pd = IO_MEM_UNASSIGNED;
20408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
20418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pd = p->phys_offset;
20428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
20458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
20468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            !(pd & IO_MEM_ROMD)) {
20478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* do nothing */
20488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
20498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            unsigned long addr1;
20508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
20518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* ROM/RAM case */
20525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ptr = qemu_get_ram_ptr(addr1);
2053a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner            memcpy(ptr, buf8, l);
2054d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney            invalidate_and_set_dirty(addr1, l);
20558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len -= l;
2057a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner        buf8 += l;
20588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr += l;
20598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
20608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct {
20635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *buffer;
2064bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner    hwaddr addr;
2065bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner    hwaddr len;
20665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} BounceBuffer;
20675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BounceBuffer bounce;
20695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct MapClient {
20715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *opaque;
20725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void (*callback)(void *opaque);
2073a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QLIST_ENTRY(MapClient) link;
20745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} MapClient;
20755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2076a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turnerstatic QLIST_HEAD(map_client_list, MapClient) map_client_list
2077a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    = QLIST_HEAD_INITIALIZER(map_client_list);
20785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
20805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2081aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    MapClient *client = g_malloc(sizeof(*client));
20825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    client->opaque = opaque;
20845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    client->callback = callback;
2085a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QLIST_INSERT_HEAD(&map_client_list, client, link);
20865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return client;
20875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
20885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20898b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turnerstatic void cpu_unregister_map_client(void *_client)
20905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
20915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    MapClient *client = (MapClient *)_client;
20925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2093a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    QLIST_REMOVE(client, link);
2094aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(client);
20955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
20965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void cpu_notify_map_clients(void)
20985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
20995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    MapClient *client;
21005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2101a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner    while (!QLIST_EMPTY(&map_client_list)) {
2102a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        client = QLIST_FIRST(&map_client_list);
21035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        client->callback(client->opaque);
21048b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner        cpu_unregister_map_client(client);
21055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
21065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
21075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Map a physical memory region into a host virtual address.
21095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * May map a subset of the requested range, given by and returned in *plen.
21105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * May return NULL if resources needed to perform the mapping are exhausted.
21115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Use only for reads OR writes - not for read-modify-write operations.
21125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Use cpu_register_map_client() to know when retrying the map operation is
21135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * likely to succeed.
21145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
2115bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnervoid *cpu_physical_memory_map(hwaddr addr,
2116bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner                              hwaddr *plen,
21175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              int is_write)
21185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2119bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner    hwaddr len = *plen;
2120bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner    hwaddr done = 0;
21215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int l;
21225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t *ret = NULL;
21235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t *ptr;
2124bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner    hwaddr page;
21255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unsigned long pd;
21265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    PhysPageDesc *p;
21275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unsigned long addr1;
21285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (len > 0) {
21305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        page = addr & TARGET_PAGE_MASK;
21315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        l = (page + TARGET_PAGE_SIZE) - addr;
21325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (l > len)
21335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            l = len;
21345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        p = phys_page_find(page >> TARGET_PAGE_BITS);
21355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!p) {
21365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            pd = IO_MEM_UNASSIGNED;
21375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
21385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            pd = p->phys_offset;
21395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
21405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
21425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (done || bounce.buffer) {
21435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
21445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
21455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
21465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bounce.addr = addr;
21475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bounce.len = l;
21485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (!is_write) {
21498b87a1d32dbee82bc393694bc87705119da0cb3bDavid 'Digit' Turner                cpu_physical_memory_read(addr, bounce.buffer, l);
21505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
21515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ptr = bounce.buffer;
21525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
21535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
21545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ptr = qemu_get_ram_ptr(addr1);
21555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
21565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!done) {
21575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = ptr;
21585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else if (ret + done != ptr) {
21595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
21605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
21615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len -= l;
21635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        addr += l;
21645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        done += l;
21655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
21665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    *plen = done;
21675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
21685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
21695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
21715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Will also mark the memory as dirty if is_write == 1.  access_len gives
21725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the amount of memory that was actually read or written by the caller.
21735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
2174bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnervoid cpu_physical_memory_unmap(void *buffer, hwaddr len,
2175bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner                               int is_write, hwaddr access_len)
21765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
21775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (buffer != bounce.buffer) {
21785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (is_write) {
2179280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner            ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
21805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            while (access_len) {
21815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                unsigned l;
21825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                l = TARGET_PAGE_SIZE;
21835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (l > access_len)
21845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    l = access_len;
2185d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney                invalidate_and_set_dirty(addr1, l);
21865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                addr1 += l;
21875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                access_len -= l;
21885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
21895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
21905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
21915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
21925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (is_write) {
21935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
21945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2195280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner    qemu_vfree(bounce.buffer);
21965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bounce.buffer = NULL;
21975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_notify_map_clients();
21985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
21998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* warning: addr must be aligned */
22012afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turnerstatic inline uint32_t ldl_phys_internal(hwaddr addr,
22022afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner                                         enum device_endian endian)
22038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int io_index;
22058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *ptr;
22068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t val;
22078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pd;
22088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PhysPageDesc *p;
22098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = phys_page_find(addr >> TARGET_PAGE_BITS);
22118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p) {
22128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pd = IO_MEM_UNASSIGNED;
22138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
22148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pd = p->phys_offset;
22158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
22188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        !(pd & IO_MEM_ROMD)) {
22198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* I/O case */
22208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
22215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (p)
22225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
2223fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        val = io_mem_read(io_index, addr, 4);
22242afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner#if defined(TARGET_WORDS_BIGENDIAN)
22252afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        if (endian == DEVICE_LITTLE_ENDIAN) {
22262afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = bswap32(val);
22272afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
22282afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner#else
22292afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        if (endian == DEVICE_BIG_ENDIAN) {
22302afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = bswap32(val);
22312afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
22322afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner#endif
22338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
22348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* RAM case */
22355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
22368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            (addr & ~TARGET_PAGE_MASK);
22372afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        switch (endian) {
22382afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            case DEVICE_LITTLE_ENDIAN:
22392afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner                val = ldl_le_p(ptr);
22402afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner                break;
22412afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            case DEVICE_BIG_ENDIAN:
22422afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner                val = ldl_be_p(ptr);
22432afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner                break;
22442afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            default:
22452afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner                val = ldl_p(ptr);
22462afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner                break;
22472afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
22488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return val;
22508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
22518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22522afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turneruint32_t ldl_phys(hwaddr addr)
22532afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
22542afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    return ldl_phys_internal(addr, DEVICE_NATIVE_ENDIAN);
22552afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
22562afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
22572afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turneruint32_t ldl_le_phys(hwaddr addr)
22582afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
22592afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    return ldl_phys_internal(addr, DEVICE_LITTLE_ENDIAN);
22602afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
22612afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
22622afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turneruint32_t ldl_be_phys(hwaddr addr)
22632afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
22642afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    return ldl_phys_internal(addr, DEVICE_BIG_ENDIAN);
22652afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
22662afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
22678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* warning: addr must be aligned */
22682afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turnerstatic inline uint64_t ldq_phys_internal(hwaddr addr,
22692afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner                                         enum device_endian endian)
22708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int io_index;
22728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *ptr;
22738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint64_t val;
22748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pd;
22758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PhysPageDesc *p;
22768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = phys_page_find(addr >> TARGET_PAGE_BITS);
22788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p) {
22798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pd = IO_MEM_UNASSIGNED;
22808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
22818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pd = p->phys_offset;
22828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
22858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        !(pd & IO_MEM_ROMD)) {
22868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* I/O case */
22878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
22885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (p)
22895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
22902afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
22912afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        /* XXX This is broken when device endian != cpu endian.
22922afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner               Fix and add "endian" variable check */
22938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TARGET_WORDS_BIGENDIAN
2294fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        val = (uint64_t)io_mem_read(io_index, addr, 4) << 32;
2295fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        val |= io_mem_read(io_index, addr + 4, 4);
22968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2297fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        val = io_mem_read(io_index, addr, 4);
2298fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        val |= (uint64_t)io_mem_read(io_index, addr + 4, 4) << 32;
22998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
23008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
23018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* RAM case */
23025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
23038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            (addr & ~TARGET_PAGE_MASK);
23042afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        switch (endian) {
23052afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        case DEVICE_LITTLE_ENDIAN:
23062afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = ldq_le_p(ptr);
23072afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            break;
23082afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        case DEVICE_BIG_ENDIAN:
23092afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = ldq_be_p(ptr);
23102afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            break;
23112afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        default:
23122afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = ldq_p(ptr);
23132afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            break;
23142afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
23158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return val;
23178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23192afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turneruint64_t ldq_phys(hwaddr addr)
23202afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
23212afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    return ldq_phys_internal(addr, DEVICE_NATIVE_ENDIAN);
23222afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
23232afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
23242afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turneruint64_t ldq_le_phys(hwaddr addr)
23252afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
23262afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    return ldq_phys_internal(addr, DEVICE_LITTLE_ENDIAN);
23272afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
23282afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
23292afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turneruint64_t ldq_be_phys(hwaddr addr)
23302afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
23312afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    return ldq_phys_internal(addr, DEVICE_BIG_ENDIAN);
23322afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
23332afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
23348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: optimize */
2335bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turneruint32_t ldub_phys(hwaddr addr)
23368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t val;
23388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_physical_memory_read(addr, &val, 1);
23398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return val;
23408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: optimize */
23432afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turnerstatic inline uint32_t lduw_phys_internal(hwaddr addr,
23442afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner                                          enum device_endian endian)
23452afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
23462afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    int io_index;
23472afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    uint8_t *ptr;
23482afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    uint64_t val;
23492afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    unsigned long pd;
23502afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    PhysPageDesc *p;
23512afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
23522afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    p = phys_page_find(addr >> TARGET_PAGE_BITS);
23532afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    if (!p) {
23542afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        pd = IO_MEM_UNASSIGNED;
23552afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    } else {
23562afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        pd = p->phys_offset;
23572afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    }
23582afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
23592afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
23602afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        !(pd & IO_MEM_ROMD)) {
23612afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        /* I/O case */
23622afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
23632afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        if (p)
23642afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
2365fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        val = io_mem_read(io_index, addr, 2);
23662afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner#if defined(TARGET_WORDS_BIGENDIAN)
23672afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        if (endian == DEVICE_LITTLE_ENDIAN) {
23682afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = bswap16(val);
23692afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
23702afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner#else
23712afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        if (endian == DEVICE_BIG_ENDIAN) {
23722afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = bswap16(val);
23732afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
23742afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner#endif
23752afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    } else {
23762afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        /* RAM case */
23772afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
23782afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            (addr & ~TARGET_PAGE_MASK);
23792afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        switch (endian) {
23802afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        case DEVICE_LITTLE_ENDIAN:
23812afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = lduw_le_p(ptr);
23822afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            break;
23832afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        case DEVICE_BIG_ENDIAN:
23842afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = lduw_be_p(ptr);
23852afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            break;
23862afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        default:
23872afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = lduw_p(ptr);
23882afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            break;
23892afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
23902afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    }
23912afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    return val;
23922afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
23932afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
2394bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turneruint32_t lduw_phys(hwaddr addr)
23958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23962afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    return lduw_phys_internal(addr, DEVICE_NATIVE_ENDIAN);
23972afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
23982afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
23992afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turneruint32_t lduw_le_phys(hwaddr addr)
24002afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
24012afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    return lduw_phys_internal(addr, DEVICE_LITTLE_ENDIAN);
24022afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
24032afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
24042afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turneruint32_t lduw_be_phys(hwaddr addr)
24052afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
24062afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    return lduw_phys_internal(addr, DEVICE_BIG_ENDIAN);
24078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* warning: addr must be aligned. The ram page is not masked as dirty
24108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   and the code inside is not invalidated. It is useful if the dirty
24118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   bits are used to track modified PTEs */
2412bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnervoid stl_phys_notdirty(hwaddr addr, uint32_t val)
24138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int io_index;
24158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *ptr;
24168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pd;
24178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PhysPageDesc *p;
24188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = phys_page_find(addr >> TARGET_PAGE_BITS);
24208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p) {
24218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pd = IO_MEM_UNASSIGNED;
24228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
24238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pd = p->phys_offset;
24248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
24278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
24285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (p)
24295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
2430fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        io_mem_write(io_index, addr, val, 4);
24318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
24325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
24335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ptr = qemu_get_ram_ptr(addr1);
24348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stl_p(ptr, val);
24355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
24365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (unlikely(in_migration)) {
24375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (!cpu_physical_memory_is_dirty(addr1)) {
24385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* invalidate code */
24395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
24405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* set dirty bit */
2441280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                cpu_physical_memory_set_dirty_flags(
2442280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                    addr1, (0xff & ~CODE_DIRTY_FLAG));
24435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
24445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
24458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2448bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnervoid stq_phys_notdirty(hwaddr addr, uint64_t val)
24498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int io_index;
24518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *ptr;
24528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pd;
24538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PhysPageDesc *p;
24548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = phys_page_find(addr >> TARGET_PAGE_BITS);
24568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p) {
24578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pd = IO_MEM_UNASSIGNED;
24588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
24598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pd = p->phys_offset;
24608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
24638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
24645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (p)
24655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
24668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TARGET_WORDS_BIGENDIAN
2467fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        io_mem_write(io_index, addr, val >> 32, 4);
2468fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        io_mem_write(io_index, addr + 4, val, 4);
24698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2470fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        io_mem_write(io_index, addr, val, 4);
2471fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        io_mem_write(io_index, addr + 4, val >> 32, 4);
24728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
24738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
24745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
24758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            (addr & ~TARGET_PAGE_MASK);
24768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stq_p(ptr, val);
24778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* warning: addr must be aligned */
24812afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turnerstatic inline void stl_phys_internal(hwaddr addr, uint32_t val,
24822afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner                                     enum device_endian endian)
24838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int io_index;
24858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *ptr;
24868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pd;
24878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PhysPageDesc *p;
24888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = phys_page_find(addr >> TARGET_PAGE_BITS);
24908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p) {
24918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pd = IO_MEM_UNASSIGNED;
24928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
24938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pd = p->phys_offset;
24948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
24978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
24985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (p)
24995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
25002afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner#if defined(TARGET_WORDS_BIGENDIAN)
25012afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        if (endian == DEVICE_LITTLE_ENDIAN) {
25022afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = bswap32(val);
25032afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
25042afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner#else
25052afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        if (endian == DEVICE_BIG_ENDIAN) {
25062afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = bswap32(val);
25072afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
25082afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner#endif
2509fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        io_mem_write(io_index, addr, val, 4);
25108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
25118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unsigned long addr1;
25128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
25138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* RAM case */
25145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ptr = qemu_get_ram_ptr(addr1);
25152afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        switch (endian) {
25162afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        case DEVICE_LITTLE_ENDIAN:
25172afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            stl_le_p(ptr, val);
25182afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            break;
25192afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        case DEVICE_BIG_ENDIAN:
25202afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            stl_be_p(ptr, val);
25212afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            break;
25222afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        default:
25232afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            stl_p(ptr, val);
25242afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            break;
25252afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
2526d09d7665187911f9aedf0951818a45b7485acbb0Pete Delaney        invalidate_and_set_dirty(addr1, 4);
25278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25302afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turnervoid stl_phys(hwaddr addr, uint32_t val)
25312afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
25322afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    stl_phys_internal(addr, val, DEVICE_NATIVE_ENDIAN);
25332afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
25342afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
25352afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turnervoid stl_le_phys(hwaddr addr, uint32_t val)
25362afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
25372afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    stl_phys_internal(addr, val, DEVICE_LITTLE_ENDIAN);
25382afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
25392afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
25402afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turnervoid stl_be_phys(hwaddr addr, uint32_t val)
25412afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
25422afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    stl_phys_internal(addr, val, DEVICE_BIG_ENDIAN);
25432afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
25442afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
25458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: optimize */
2546bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnervoid stb_phys(hwaddr addr, uint32_t val)
25478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t v = val;
25498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_physical_memory_write(addr, &v, 1);
25508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: optimize */
25532afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turnerstatic inline void stw_phys_internal(hwaddr addr, uint32_t val,
25542afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner                                     enum device_endian endian)
25552afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
25562afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    int io_index;
25572afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    uint8_t *ptr;
25582afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    unsigned long pd;
25592afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    PhysPageDesc *p;
25602afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
25612afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    p = phys_page_find(addr >> TARGET_PAGE_BITS);
25622afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    if (!p) {
25632afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        pd = IO_MEM_UNASSIGNED;
25642afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    } else {
25652afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        pd = p->phys_offset;
25662afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    }
25672afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
25682afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
25692afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
25702afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        if (p)
25712afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
25722afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner#if defined(TARGET_WORDS_BIGENDIAN)
25732afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        if (endian == DEVICE_LITTLE_ENDIAN) {
25742afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = bswap16(val);
25752afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
25762afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner#else
25772afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        if (endian == DEVICE_BIG_ENDIAN) {
25782afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            val = bswap16(val);
25792afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
25802afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner#endif
2581fdec1f1b82ec4e5ce7b62b8120ba5b1218a9c0afDavid 'Digit' Turner        io_mem_write(io_index, addr, val, 2);
25822afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    } else {
25832afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        unsigned long addr1;
25842afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
25852afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        /* RAM case */
25862afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        ptr = qemu_get_ram_ptr(addr1);
25872afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        switch (endian) {
25882afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        case DEVICE_LITTLE_ENDIAN:
25892afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            stw_le_p(ptr, val);
25902afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            break;
25912afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        case DEVICE_BIG_ENDIAN:
25922afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            stw_be_p(ptr, val);
25932afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            break;
25942afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        default:
25952afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            stw_p(ptr, val);
25962afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            break;
25972afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
25982afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        if (!cpu_physical_memory_is_dirty(addr1)) {
25992afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            /* invalidate code */
26002afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            tb_invalidate_phys_page_range(addr1, addr1 + 2, 0);
26012afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            /* set dirty bit */
26022afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner            cpu_physical_memory_set_dirty_flags(addr1,
26032afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner                (0xff & ~CODE_DIRTY_FLAG));
26042afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner        }
26052afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    }
26062afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
26072afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
2608bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnervoid stw_phys(hwaddr addr, uint32_t val)
26098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26102afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    stw_phys_internal(addr, val, DEVICE_NATIVE_ENDIAN);
26112afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
26122afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
26132afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turnervoid stw_le_phys(hwaddr addr, uint32_t val)
26142afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
26152afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    stw_phys_internal(addr, val, DEVICE_LITTLE_ENDIAN);
26162afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
26172afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
26182afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turnervoid stw_be_phys(hwaddr addr, uint32_t val)
26192afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
26202afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    stw_phys_internal(addr, val, DEVICE_BIG_ENDIAN);
26218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: optimize */
2624bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnervoid stq_phys(hwaddr addr, uint64_t val)
26258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    val = tswap64(val);
26272afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    cpu_physical_memory_write(addr, &val, 8);
26282afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
26292afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
26302afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
26312afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turnervoid stq_le_phys(hwaddr addr, uint64_t val)
26322afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
26332afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    val = cpu_to_le64(val);
26342afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    cpu_physical_memory_write(addr, &val, 8);
26352afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner}
26362afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner
26372afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turnervoid stq_be_phys(hwaddr addr, uint64_t val)
26382afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner{
26392afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    val = cpu_to_be64(val);
26402afeb4c534203d6ab9ce2b003315ff8c25083a31David 'Digit' Turner    cpu_physical_memory_write(addr, &val, 8);
26418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
26448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* virtual memory access for debug (includes writing to ROM) */
2646aaef275467ba13162d52ef6f690fd97f9733eb58David 'Digit' Turnerint cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
2647a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner                        void *buf, int len, int is_write)
26488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int l;
2650bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner    hwaddr phys_addr;
26518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong page;
2652a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner    uint8_t* buf8 = (uint8_t*)buf;
2653aaef275467ba13162d52ef6f690fd97f9733eb58David 'Digit' Turner    CPUArchState *env = cpu->env_ptr;
26548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (len > 0) {
26568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        page = addr & TARGET_PAGE_MASK;
26578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        phys_addr = cpu_get_phys_page_debug(env, page);
26588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* if no physical page mapped, return an error */
26598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (phys_addr == -1)
26608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
26618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        l = (page + TARGET_PAGE_SIZE) - addr;
26628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (l > len)
26638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            l = len;
26645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        phys_addr += (addr & ~TARGET_PAGE_MASK);
26655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if !defined(CONFIG_USER_ONLY)
26665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (is_write)
2667a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner            cpu_physical_memory_write_rom(phys_addr, buf8, l);
26685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else
26695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
2670a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner            cpu_physical_memory_rw(phys_addr, buf8, l, is_write);
26718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len -= l;
2672a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner        buf8 += l;
26738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr += l;
26748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
26758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
26768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2677