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