blob: b22b2b8cb5165f0f3edd0df21d3cc09f7e8b40c0 [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/*
2 * virtual page mapping and translated block handling
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080018 */
19#include "config.h"
20#ifdef _WIN32
21#define WIN32_LEAN_AND_MEAN
22#include <windows.h>
23#else
24#include <sys/types.h>
25#include <sys/mman.h>
26#endif
27#include <stdlib.h>
28#include <stdio.h>
29#include <stdarg.h>
30#include <string.h>
31#include <errno.h>
32#include <unistd.h>
33#include <inttypes.h>
34
35#include "cpu.h"
David 'Digit' Turner852088c2013-12-14 23:04:12 +010036#include "exec/exec-all.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080037#include "qemu-common.h"
38#include "tcg.h"
39#include "hw/hw.h"
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +010040#include "hw/xen/xen.h"
David 'Digit' Turner84569132013-12-13 17:34:07 +010041#include "qemu/osdep.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010042#include "sysemu/kvm.h"
David 'Digit' Turner3dc53fc2014-01-17 01:23:40 +010043#include "exec/cputlb.h"
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +010044#include "exec/hax.h"
David 'Digit' Turner7a78db72013-12-14 11:46:01 +010045#include "qemu/timer.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080046#if defined(CONFIG_USER_ONLY)
47#include <qemu.h>
48#endif
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -080049#ifdef CONFIG_MEMCHECK
50#include "memcheck/memcheck_api.h"
51#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080052
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080053//#define DEBUG_SUBPAGE
54
55#if !defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080056int phys_ram_fd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070057static int in_migration;
58
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +010059RAMList ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) };
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080060#endif
61
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +010062CPUArchState *first_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080063/* current CPU in the current thread. It is only valid inside
64 cpu_exec() */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +010065CPUArchState *cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080066/* 0 = Do not count executed instructions.
67 1 = Precise instruction counting.
68 2 = Adaptive rate instruction counting. */
69int use_icount = 0;
70/* Current instruction counter. While executing translated code this may
71 include some instructions that have not yet been executed. */
72int64_t qemu_icount;
73
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080074#if !defined(CONFIG_USER_ONLY)
75static void io_mem_init(void);
76
77/* io memory support */
78CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
79CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
80void *io_mem_opaque[IO_MEM_NB_ENTRIES];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070081static char io_mem_used[IO_MEM_NB_ENTRIES];
David 'Digit' Turner3dc53fc2014-01-17 01:23:40 +010082int io_mem_watch;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080083#endif
84
85/* log support */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070086#ifdef WIN32
87static const char *logfilename = "qemu.log";
88#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070089static const char *logfilename = "/tmp/qemu.log";
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070090#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080091FILE *logfile;
92int loglevel;
93static int log_append = 0;
94
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080095#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
96typedef struct subpage_t {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +010097 hwaddr base;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080098 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
99 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
100 void *opaque[TARGET_PAGE_SIZE][2][4];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700101 ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800102} subpage_t;
103
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800104/* Must be called before using the QEMU cpus. 'tb_size' is the size
105 (in bytes) allocated to the translation buffer. Zero means default
106 size. */
107void cpu_exec_init_all(unsigned long tb_size)
108{
David 'Digit' Turnerff9a2b82014-02-17 22:31:24 +0100109 //cpu_gen_init();
110 //code_gen_alloc(tb_size);
111 //code_gen_ptr = code_gen_buffer;
112 //page_init();
113 tcg_exec_init(tb_size);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800114#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +0100115 qemu_mutex_init(&ram_list.mutex);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800116 io_mem_init();
117#endif
118}
119
120#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
121
122#define CPU_COMMON_SAVE_VERSION 1
123
124static void cpu_common_save(QEMUFile *f, void *opaque)
125{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100126 CPUOldState *env = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800127
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700128 cpu_synchronize_state(env, 0);
129
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800130 qemu_put_be32s(f, &env->halted);
131 qemu_put_be32s(f, &env->interrupt_request);
132}
133
134static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
135{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100136 CPUOldState *env = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800137
138 if (version_id != CPU_COMMON_SAVE_VERSION)
139 return -EINVAL;
140
141 qemu_get_be32s(f, &env->halted);
142 qemu_get_be32s(f, &env->interrupt_request);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700143 /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
144 version_id is increased. */
145 env->interrupt_request &= ~0x01;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800146 tlb_flush(env, 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700147 cpu_synchronize_state(env, 1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800148
149 return 0;
150}
151#endif
152
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100153CPUArchState *qemu_get_cpu(int cpu)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700154{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100155 CPUArchState *env = first_cpu;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700156
157 while (env) {
158 if (env->cpu_index == cpu)
159 break;
160 env = env->next_cpu;
161 }
162
163 return env;
164}
165
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100166void cpu_exec_init(CPUArchState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800167{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100168 CPUArchState **penv;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800169 int cpu_index;
170
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700171#if defined(CONFIG_USER_ONLY)
172 cpu_list_lock();
173#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800174 env->next_cpu = NULL;
175 penv = &first_cpu;
176 cpu_index = 0;
177 while (*penv != NULL) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700178 penv = &(*penv)->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800179 cpu_index++;
180 }
181 env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700182 env->numa_node = 0;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700183 QTAILQ_INIT(&env->breakpoints);
184 QTAILQ_INIT(&env->watchpoints);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800185 *penv = env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700186#if defined(CONFIG_USER_ONLY)
187 cpu_list_unlock();
188#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800189#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5cb5c0b2014-02-17 16:04:03 +0100190 register_savevm(NULL,
191 "cpu_common",
192 cpu_index,
193 CPU_COMMON_SAVE_VERSION,
194 cpu_common_save,
195 cpu_common_load,
196 env);
197 register_savevm(NULL,
198 "cpu",
199 cpu_index,
200 CPU_SAVE_VERSION,
201 cpu_save,
202 cpu_load,
203 env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800204#endif
205}
206
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800207#if defined(TARGET_HAS_ICE)
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100208static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800209{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100210 hwaddr addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800211 target_ulong pd;
212 ram_addr_t ram_addr;
213 PhysPageDesc *p;
214
215 addr = cpu_get_phys_page_debug(env, pc);
216 p = phys_page_find(addr >> TARGET_PAGE_BITS);
217 if (!p) {
218 pd = IO_MEM_UNASSIGNED;
219 } else {
220 pd = p->phys_offset;
221 }
222 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
223 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
224}
225#endif
226
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100227#if defined(CONFIG_USER_ONLY)
228void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
229
230{
231}
232
233int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
234 int flags, CPUWatchpoint **watchpoint)
235{
236 return -ENOSYS;
237}
238#else
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800239/* Add a watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100240int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700241 int flags, CPUWatchpoint **watchpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800242{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700243 target_ulong len_mask = ~(len - 1);
244 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800245
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700246 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100247 if ((len & (len - 1)) || (addr & ~len_mask) ||
248 len == 0 || len > TARGET_PAGE_SIZE) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700249 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
250 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
251 return -EINVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800252 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100253 wp = g_malloc(sizeof(*wp));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800254
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700255 wp->vaddr = addr;
256 wp->len_mask = len_mask;
257 wp->flags = flags;
258
259 /* keep all GDB-injected watchpoints in front */
260 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700261 QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700262 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700263 QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700264
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800265 tlb_flush_page(env, addr);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700266
267 if (watchpoint)
268 *watchpoint = wp;
269 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800270}
271
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700272/* Remove a specific watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100273int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700274 int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800275{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700276 target_ulong len_mask = ~(len - 1);
277 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800278
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700279 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700280 if (addr == wp->vaddr && len_mask == wp->len_mask
281 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
282 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800283 return 0;
284 }
285 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700286 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800287}
288
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700289/* Remove a specific watchpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100290void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700291{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700292 QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800293
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700294 tlb_flush_page(env, watchpoint->vaddr);
295
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100296 g_free(watchpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700297}
298
299/* Remove all matching watchpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100300void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700301{
302 CPUWatchpoint *wp, *next;
303
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700304 QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700305 if (wp->flags & mask)
306 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800307 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800308}
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100309#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800310
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700311/* Add a breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100312int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700313 CPUBreakpoint **breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800314{
315#if defined(TARGET_HAS_ICE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700316 CPUBreakpoint *bp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800317
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100318 bp = g_malloc(sizeof(*bp));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700319
320 bp->pc = pc;
321 bp->flags = flags;
322
323 /* keep all GDB-injected breakpoints in front */
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100324 if (flags & BP_GDB) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700325 QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100326 } else {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700327 QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100328 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700329
330 breakpoint_invalidate(env, pc);
331
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100332 if (breakpoint) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700333 *breakpoint = bp;
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100334 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700335 return 0;
336#else
337 return -ENOSYS;
338#endif
339}
340
341/* Remove a specific breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100342int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700343{
344#if defined(TARGET_HAS_ICE)
345 CPUBreakpoint *bp;
346
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700347 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700348 if (bp->pc == pc && bp->flags == flags) {
349 cpu_breakpoint_remove_by_ref(env, bp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800350 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700351 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800352 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700353 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800354#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700355 return -ENOSYS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800356#endif
357}
358
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700359/* Remove a specific breakpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100360void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800361{
362#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700363 QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800364
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700365 breakpoint_invalidate(env, breakpoint->pc);
366
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100367 g_free(breakpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700368#endif
369}
370
371/* Remove all matching breakpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100372void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700373{
374#if defined(TARGET_HAS_ICE)
375 CPUBreakpoint *bp, *next;
376
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700377 QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700378 if (bp->flags & mask)
379 cpu_breakpoint_remove_by_ref(env, bp);
380 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800381#endif
382}
383
384/* enable or disable single step mode. EXCP_DEBUG is returned by the
385 CPU loop after each instruction */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100386void cpu_single_step(CPUOldState *env, int enabled)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800387{
388#if defined(TARGET_HAS_ICE)
389 if (env->singlestep_enabled != enabled) {
390 env->singlestep_enabled = enabled;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700391 if (kvm_enabled())
392 kvm_update_guest_debug(env, 0);
393 else {
394 /* must flush all the translated code to avoid inconsistencies */
395 /* XXX: only flush what is necessary */
396 tb_flush(env);
397 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800398 }
399#endif
400}
401
402/* enable or disable low levels log */
403void cpu_set_log(int log_flags)
404{
405 loglevel = log_flags;
406 if (loglevel && !logfile) {
407 logfile = fopen(logfilename, log_append ? "a" : "w");
408 if (!logfile) {
409 perror(logfilename);
Iliyan Malchev4a2c9dd2012-04-02 08:20:56 -0700410 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800411 }
412#if !defined(CONFIG_SOFTMMU)
413 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
414 {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700415 static char logfile_buf[4096];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800416 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
417 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700418#elif !defined(_WIN32)
419 /* Win32 doesn't support line-buffering and requires size >= 2 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800420 setvbuf(logfile, NULL, _IOLBF, 0);
421#endif
422 log_append = 1;
423 }
424 if (!loglevel && logfile) {
425 fclose(logfile);
426 logfile = NULL;
427 }
428}
429
430void cpu_set_log_filename(const char *filename)
431{
432 logfilename = strdup(filename);
433 if (logfile) {
434 fclose(logfile);
435 logfile = NULL;
436 }
437 cpu_set_log(loglevel);
438}
439
David 'Digit' Turner3e0677d2014-03-07 15:01:06 +0100440void cpu_unlink_tb(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800441{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800442 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
443 problem and hope the cpu will stop of its own accord. For userspace
444 emulation this often isn't actually as bad as it sounds. Often
445 signals are used primarily to interrupt blocking syscalls. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700446 TranslationBlock *tb;
447 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
448
David 'Digit' Turner795bb192011-05-09 15:20:22 +0200449 spin_lock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700450 tb = env->current_tb;
451 /* if the cpu is currently executing code, we must unlink it and
452 all the potentially executing TB */
David 'Digit' Turner795bb192011-05-09 15:20:22 +0200453 if (tb) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700454 env->current_tb = NULL;
455 tb_reset_jump_recursive(tb);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700456 }
David 'Digit' Turner795bb192011-05-09 15:20:22 +0200457 spin_unlock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700458}
459
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100460void cpu_reset_interrupt(CPUOldState *env, int mask)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800461{
462 env->interrupt_request &= ~mask;
463}
464
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100465void cpu_exit(CPUOldState *env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700466{
467 env->exit_request = 1;
468 cpu_unlink_tb(env);
469}
470
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100471void cpu_abort(CPUArchState *env, const char *fmt, ...)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800472{
473 va_list ap;
474 va_list ap2;
475
476 va_start(ap, fmt);
477 va_copy(ap2, ap);
478 fprintf(stderr, "qemu: fatal: ");
479 vfprintf(stderr, fmt, ap);
480 fprintf(stderr, "\n");
481#ifdef TARGET_I386
482 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
483#else
484 cpu_dump_state(env, stderr, fprintf, 0);
485#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700486 if (qemu_log_enabled()) {
487 qemu_log("qemu: fatal: ");
488 qemu_log_vprintf(fmt, ap2);
489 qemu_log("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800490#ifdef TARGET_I386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700491 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800492#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700493 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800494#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700495 qemu_log_flush();
496 qemu_log_close();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800497 }
498 va_end(ap2);
499 va_end(ap);
David 'Digit' Turner36411062010-12-22 17:34:53 +0100500#if defined(CONFIG_USER_ONLY)
501 {
502 struct sigaction act;
503 sigfillset(&act.sa_mask);
504 act.sa_handler = SIG_DFL;
505 sigaction(SIGABRT, &act, NULL);
506 }
507#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800508 abort();
509}
510
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100511CPUArchState *cpu_copy(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800512{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100513 CPUArchState *new_env = cpu_init(env->cpu_model_str);
514 CPUArchState *next_cpu = new_env->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800515 int cpu_index = new_env->cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700516#if defined(TARGET_HAS_ICE)
517 CPUBreakpoint *bp;
518 CPUWatchpoint *wp;
519#endif
520
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100521 memcpy(new_env, env, sizeof(CPUOldState));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700522
523 /* Preserve chaining and index. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800524 new_env->next_cpu = next_cpu;
525 new_env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700526
527 /* Clone all break/watchpoints.
528 Note: Once we support ptrace with hw-debug register access, make sure
529 BP_CPU break/watchpoints are handled correctly on clone. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700530 QTAILQ_INIT(&env->breakpoints);
531 QTAILQ_INIT(&env->watchpoints);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700532#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700533 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700534 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
535 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700536 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700537 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
538 wp->flags, NULL);
539 }
540#endif
541
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800542 return new_env;
543}
544
545#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +0100546static RAMBlock *qemu_get_ram_block(ram_addr_t addr)
547{
548 RAMBlock *block;
549
550 /* The list is protected by the iothread lock here. */
551 block = ram_list.mru_block;
552 if (block && addr - block->offset < block->length) {
553 goto found;
554 }
555 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
556 if (addr - block->offset < block->length) {
557 goto found;
558 }
559 }
560
561 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
562 abort();
563
564found:
565 ram_list.mru_block = block;
566 return block;
567}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800568
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700569/* Note: start and end must be within the same ram block. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800570void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
571 int dirty_flags)
572{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100573 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800574 unsigned long length, start1;
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200575 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800576
577 start &= TARGET_PAGE_MASK;
578 end = TARGET_PAGE_ALIGN(end);
579
580 length = end - start;
581 if (length == 0)
582 return;
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200583 cpu_physical_memory_mask_dirty_range(start, length, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800584
585 /* we modify the TLB cache so that the dirty bit will be set again
586 when accessing the range */
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200587 start1 = (unsigned long)qemu_safe_ram_ptr(start);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700588 /* Chek that we don't span multiple blocks - this breaks the
589 address comparisons below. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200590 if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700591 != (end - 1) - start) {
592 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800593 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700594
595 for(env = first_cpu; env != NULL; env = env->next_cpu) {
596 int mmu_idx;
597 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
598 for(i = 0; i < CPU_TLB_SIZE; i++)
599 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
600 start1, length);
601 }
602 }
603}
604
605int cpu_physical_memory_set_dirty_tracking(int enable)
606{
607 in_migration = enable;
608 if (kvm_enabled()) {
609 return kvm_set_migration_log(enable);
610 }
611 return 0;
612}
613
614int cpu_physical_memory_get_dirty_tracking(void)
615{
616 return in_migration;
617}
618
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100619int cpu_physical_sync_dirty_bitmap(hwaddr start_addr,
620 hwaddr end_addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700621{
622 int ret = 0;
623
624 if (kvm_enabled())
625 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
626 return ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800627}
628
629static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
630{
631 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700632 void *p;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800633
634 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700635 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
636 + tlb_entry->addend);
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200637 ram_addr = qemu_ram_addr_from_host_nofail(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800638 if (!cpu_physical_memory_is_dirty(ram_addr)) {
639 tlb_entry->addr_write |= TLB_NOTDIRTY;
640 }
641 }
642}
643
644/* update the TLB according to the current state of the dirty bits */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100645void cpu_tlb_update_dirty(CPUArchState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800646{
647 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700648 int mmu_idx;
649 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
650 for(i = 0; i < CPU_TLB_SIZE; i++)
651 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
652 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800653}
654
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800655
656#else
657
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100658void tlb_flush(CPUArchState *env, int flush_global)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800659{
660}
661
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100662void tlb_flush_page(CPUArchState *env, target_ulong addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800663{
664}
665
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100666int tlb_set_page_exec(CPUArchState *env, target_ulong vaddr,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100667 hwaddr paddr, int prot,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800668 int mmu_idx, int is_softmmu)
669{
670 return 0;
671}
672
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100673static inline void tlb_set_dirty(CPUOldState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800674 unsigned long addr, target_ulong vaddr)
675{
676}
677#endif /* defined(CONFIG_USER_ONLY) */
678
679#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700680
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800681static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700682 ram_addr_t memory, ram_addr_t region_offset);
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100683static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700684 ram_addr_t orig_memory, ram_addr_t region_offset);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +0100685
686static void *(*phys_mem_alloc)(size_t size) = qemu_anon_ram_alloc;
687
688/*
689 * Set a custom physical guest memory alloator.
690 * Accelerators with unusual needs may need this. Hopefully, we can
691 * get rid of it eventually.
692 */
693void phys_mem_set_alloc(void *(*alloc)(size_t))
694{
695 phys_mem_alloc = alloc;
696}
697
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800698#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
699 need_subpage) \
700 do { \
701 if (addr > start_addr) \
702 start_addr2 = 0; \
703 else { \
704 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
705 if (start_addr2 > 0) \
706 need_subpage = 1; \
707 } \
708 \
709 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
710 end_addr2 = TARGET_PAGE_SIZE - 1; \
711 else { \
712 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
713 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
714 need_subpage = 1; \
715 } \
716 } while (0)
717
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700718/* register physical memory.
719 For RAM, 'size' must be a multiple of the target page size.
720 If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700721 io memory page. The address used when calling the IO function is
722 the offset from the start of the region, plus region_offset. Both
723 start_addr and region_offset are rounded down to a page boundary
724 before calculating this offset. This should not be a problem unless
725 the low bits of start_addr and region_offset differ. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100726void cpu_register_physical_memory_log(hwaddr start_addr,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700727 ram_addr_t size,
728 ram_addr_t phys_offset,
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200729 ram_addr_t region_offset,
730 bool log_dirty)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800731{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100732 hwaddr addr, end_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800733 PhysPageDesc *p;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100734 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800735 ram_addr_t orig_size = size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200736 subpage_t *subpage;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800737
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700738 if (kvm_enabled())
739 kvm_set_phys_mem(start_addr, size, phys_offset);
Jun Nakajimaa381ef02011-12-17 19:13:25 -0800740#ifdef CONFIG_HAX
741 if (hax_enabled())
742 hax_set_phys_mem(start_addr, size, phys_offset);
743#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700744
745 if (phys_offset == IO_MEM_UNASSIGNED) {
746 region_offset = start_addr;
747 }
748 region_offset &= TARGET_PAGE_MASK;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800749 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100750 end_addr = start_addr + (hwaddr)size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200751
752 addr = start_addr;
753 do {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800754 p = phys_page_find(addr >> TARGET_PAGE_BITS);
755 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
756 ram_addr_t orig_memory = p->phys_offset;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100757 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800758 int need_subpage = 0;
759
760 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
761 need_subpage);
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200762 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800763 if (!(orig_memory & IO_MEM_SUBPAGE)) {
764 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700765 &p->phys_offset, orig_memory,
766 p->region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800767 } else {
768 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
769 >> IO_MEM_SHIFT];
770 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700771 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
772 region_offset);
773 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800774 } else {
775 p->phys_offset = phys_offset;
776 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
777 (phys_offset & IO_MEM_ROMD))
778 phys_offset += TARGET_PAGE_SIZE;
779 }
780 } else {
781 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
782 p->phys_offset = phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700783 p->region_offset = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800784 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700785 (phys_offset & IO_MEM_ROMD)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800786 phys_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700787 } else {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100788 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800789 int need_subpage = 0;
790
791 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
792 end_addr2, need_subpage);
793
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200794 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800795 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700796 &p->phys_offset, IO_MEM_UNASSIGNED,
797 addr & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800798 subpage_register(subpage, start_addr2, end_addr2,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700799 phys_offset, region_offset);
800 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800801 }
802 }
803 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700804 region_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200805 addr += TARGET_PAGE_SIZE;
806 } while (addr != end_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800807
808 /* since each CPU stores ram addresses in its TLB cache, we must
809 reset the modified entries */
810 /* XXX: slow ! */
811 for(env = first_cpu; env != NULL; env = env->next_cpu) {
812 tlb_flush(env, 1);
813 }
814}
815
816/* XXX: temporary until new memory mapping API */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100817ram_addr_t cpu_get_physical_page_desc(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800818{
819 PhysPageDesc *p;
820
821 p = phys_page_find(addr >> TARGET_PAGE_BITS);
822 if (!p)
823 return IO_MEM_UNASSIGNED;
824 return p->phys_offset;
825}
826
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100827void qemu_register_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700828{
829 if (kvm_enabled())
830 kvm_coalesce_mmio_region(addr, size);
831}
832
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100833void qemu_unregister_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700834{
835 if (kvm_enabled())
836 kvm_uncoalesce_mmio_region(addr, size);
837}
838
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +0100839void qemu_mutex_lock_ramlist(void)
840{
841 qemu_mutex_lock(&ram_list.mutex);
842}
843
844void qemu_mutex_unlock_ramlist(void)
845{
846 qemu_mutex_unlock(&ram_list.mutex);
847}
848
849#if defined(__linux__) && !defined(CONFIG_ANDROID)
850
851#include <sys/vfs.h>
852
853#define HUGETLBFS_MAGIC 0x958458f6
854
855static long gethugepagesize(const char *path)
856{
857 struct statfs fs;
858 int ret;
859
860 do {
861 ret = statfs(path, &fs);
862 } while (ret != 0 && errno == EINTR);
863
864 if (ret != 0) {
865 perror(path);
866 return 0;
867 }
868
869 if (fs.f_type != HUGETLBFS_MAGIC)
870 fprintf(stderr, "Warning: path not on HugeTLBFS: %s\n", path);
871
872 return fs.f_bsize;
873}
874
875static sigjmp_buf sigjump;
876
877static void sigbus_handler(int signal)
878{
879 siglongjmp(sigjump, 1);
880}
881
882static void *file_ram_alloc(RAMBlock *block,
883 ram_addr_t memory,
884 const char *path)
885{
886 char *filename;
887 char *sanitized_name;
888 char *c;
889 void *area;
890 int fd;
891 unsigned long hpagesize;
892
893 hpagesize = gethugepagesize(path);
894 if (!hpagesize) {
895 return NULL;
896 }
897
898 if (memory < hpagesize) {
899 return NULL;
900 }
901
902 if (kvm_enabled() && !kvm_has_sync_mmu()) {
903 fprintf(stderr, "host lacks kvm mmu notifiers, -mem-path unsupported\n");
904 return NULL;
905 }
906
907 /* Make name safe to use with mkstemp by replacing '/' with '_'. */
908 sanitized_name = g_strdup(block->mr->name);
909 for (c = sanitized_name; *c != '\0'; c++) {
910 if (*c == '/')
911 *c = '_';
912 }
913
914 filename = g_strdup_printf("%s/qemu_back_mem.%s.XXXXXX", path,
915 sanitized_name);
916 g_free(sanitized_name);
917
918 fd = mkstemp(filename);
919 if (fd < 0) {
920 perror("unable to create backing store for hugepages");
921 g_free(filename);
922 return NULL;
923 }
924 unlink(filename);
925 g_free(filename);
926
927 memory = (memory+hpagesize-1) & ~(hpagesize-1);
928
929 /*
930 * ftruncate is not supported by hugetlbfs in older
931 * hosts, so don't bother bailing out on errors.
932 * If anything goes wrong with it under other filesystems,
933 * mmap will fail.
934 */
935 if (ftruncate(fd, memory))
936 perror("ftruncate");
937
938 area = mmap(0, memory, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
939 if (area == MAP_FAILED) {
940 perror("file_ram_alloc: can't mmap RAM pages");
941 close(fd);
942 return (NULL);
943 }
944
945 if (mem_prealloc) {
946 int ret, i;
947 struct sigaction act, oldact;
948 sigset_t set, oldset;
949
950 memset(&act, 0, sizeof(act));
951 act.sa_handler = &sigbus_handler;
952 act.sa_flags = 0;
953
954 ret = sigaction(SIGBUS, &act, &oldact);
955 if (ret) {
956 perror("file_ram_alloc: failed to install signal handler");
957 exit(1);
958 }
959
960 /* unblock SIGBUS */
961 sigemptyset(&set);
962 sigaddset(&set, SIGBUS);
963 pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
964
965 if (sigsetjmp(sigjump, 1)) {
966 fprintf(stderr, "file_ram_alloc: failed to preallocate pages\n");
967 exit(1);
968 }
969
970 /* MAP_POPULATE silently ignores failures */
971 for (i = 0; i < (memory/hpagesize)-1; i++) {
972 memset(area + (hpagesize*i), 0, 1);
973 }
974
975 ret = sigaction(SIGBUS, &oldact, NULL);
976 if (ret) {
977 perror("file_ram_alloc: failed to reinstall signal handler");
978 exit(1);
979 }
980
981 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
982 }
983
984 block->fd = fd;
985 return area;
986}
987#else
988static void *file_ram_alloc(RAMBlock *block,
989 ram_addr_t memory,
990 const char *path)
991{
992 fprintf(stderr, "-mem-path not supported on this host\n");
993 exit(1);
994}
995#endif
996
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200997static ram_addr_t find_ram_offset(ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700998{
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200999 RAMBlock *block, *next_block;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001000 ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001001
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001002 assert(size != 0); /* it would hand out same offset multiple times */
1003
1004 if (QTAILQ_EMPTY(&ram_list.blocks))
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001005 return 0;
1006
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001007 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1008 ram_addr_t end, next = RAM_ADDR_MAX;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001009
1010 end = block->offset + block->length;
1011
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001012 QTAILQ_FOREACH(next_block, &ram_list.blocks, next) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001013 if (next_block->offset >= end) {
1014 next = MIN(next, next_block->offset);
1015 }
1016 }
1017 if (next - end >= size && next - end < mingap) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001018 offset = end;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001019 mingap = next - end;
1020 }
1021 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001022
1023 if (offset == RAM_ADDR_MAX) {
1024 fprintf(stderr, "Failed to find gap of requested size: %" PRIu64 "\n",
1025 (uint64_t)size);
1026 abort();
1027 }
1028
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001029 return offset;
1030}
1031
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001032ram_addr_t last_ram_offset(void)
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001033{
1034 RAMBlock *block;
1035 ram_addr_t last = 0;
1036
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001037 QTAILQ_FOREACH(block, &ram_list.blocks, next)
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001038 last = MAX(last, block->offset + block->length);
1039
1040 return last;
1041}
1042
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001043static void qemu_ram_setup_dump(void *addr, ram_addr_t size)
1044{
1045#ifndef CONFIG_ANDROID
1046 int ret;
1047
1048 /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */
1049 if (!qemu_opt_get_bool(qemu_get_machine_opts(),
1050 "dump-guest-core", true)) {
1051 ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP);
1052 if (ret) {
1053 perror("qemu_madvise");
1054 fprintf(stderr, "madvise doesn't support MADV_DONTDUMP, "
1055 "but dump_guest_core=off specified\n");
1056 }
1057 }
1058#endif // !CONFIG_ANDROID
1059}
1060
1061void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001062{
1063 RAMBlock *new_block, *block;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001064
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001065 new_block = NULL;
1066 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1067 if (block->offset == addr) {
1068 new_block = block;
1069 break;
1070 }
1071 }
1072 assert(new_block);
1073 assert(!new_block->idstr[0]);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001074
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001075 if (dev) {
1076 char *id = qdev_get_dev_path(dev);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001077 if (id) {
1078 snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001079 g_free(id);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001080 }
1081 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001082 pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
1083
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001084 /* This assumes the iothread lock is taken here too. */
1085 qemu_mutex_lock_ramlist();
1086 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1087 if (block != new_block && !strcmp(block->idstr, new_block->idstr)) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001088 fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
1089 new_block->idstr);
1090 abort();
1091 }
1092 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001093 qemu_mutex_unlock_ramlist();
1094}
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001095
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001096static int memory_try_enable_merging(void *addr, size_t len)
1097{
1098#ifndef CONFIG_ANDROID
1099 if (!qemu_opt_get_bool(qemu_get_machine_opts(), "mem-merge", true)) {
1100 /* disabled by the user */
1101 return 0;
1102 }
1103
1104 return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE);
1105#else // CONFIG_ANDROID
1106 return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE);
1107#endif // CONFIG_ANDROID
1108}
1109
1110ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
1111 ram_addr_t size, void *host)
1112{
1113 RAMBlock *block, *new_block;
1114
1115 size = TARGET_PAGE_ALIGN(size);
1116 new_block = g_malloc0(sizeof(*new_block));
1117 new_block->fd = -1;
1118
1119 /* This assumes the iothread lock is taken here too. */
1120 qemu_mutex_lock_ramlist();
1121 //new_block->mr = mr;
1122 new_block->offset = find_ram_offset(size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001123 if (host) {
1124 new_block->host = host;
1125 new_block->flags |= RAM_PREALLOC_MASK;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001126 } else if (xen_enabled()) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001127 if (mem_path) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001128 fprintf(stderr, "-mem-path not supported with Xen\n");
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001129 exit(1);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001130 }
1131 //xen_ram_alloc(new_block->offset, size, mr);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001132 } else {
1133 if (mem_path) {
1134 if (phys_mem_alloc != qemu_anon_ram_alloc) {
1135 /*
1136 * file_ram_alloc() needs to allocate just like
1137 * phys_mem_alloc, but we haven't bothered to provide
1138 * a hook there.
1139 */
1140 fprintf(stderr,
1141 "-mem-path not supported with this accelerator\n");
1142 exit(1);
1143 }
1144 new_block->host = file_ram_alloc(new_block, size, mem_path);
1145 }
1146 if (!new_block->host) {
1147 new_block->host = phys_mem_alloc(size);
1148 if (!new_block->host) {
1149 fprintf(stderr, "Cannot set up guest memory '%s': %s\n",
1150 name, strerror(errno));
1151 exit(1);
1152 }
David 'Digit' Turnerf2de2ae2014-03-07 16:25:58 +01001153#ifdef CONFIG_HAX
1154 if (hax_enabled()) {
1155 /*
1156 * In HAX, qemu allocates the virtual address, and HAX kernel
1157 * module populates the region with physical memory. Currently
1158 * we don’t populate guest memory on demand, thus we should
1159 * make sure that sufficient amount of memory is available in
1160 * advance.
1161 */
1162 int ret = hax_populate_ram(
1163 (uint64_t)(uintptr_t)new_block->host,
1164 (uint32_t)size);
1165 if (ret < 0) {
1166 fprintf(stderr, "Hax failed to populate ram\n");
1167 exit(-1);
1168 }
1169 }
1170#endif // CONFIG_HAX
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001171 memory_try_enable_merging(new_block->host, size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001172 }
1173 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001174 new_block->length = size;
1175
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001176 /* Keep the list sorted from biggest to smallest block. */
1177 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1178 if (block->length < new_block->length) {
1179 break;
1180 }
1181 }
1182 if (block) {
1183 QTAILQ_INSERT_BEFORE(block, new_block, next);
1184 } else {
1185 QTAILQ_INSERT_TAIL(&ram_list.blocks, new_block, next);
1186 }
1187 ram_list.mru_block = NULL;
1188
1189 ram_list.version++;
1190 qemu_mutex_unlock_ramlist();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001191
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001192 ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001193 last_ram_offset() >> TARGET_PAGE_BITS);
1194 memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001195 0xff, size >> TARGET_PAGE_BITS);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001196 //cpu_physical_memory_set_dirty_range(new_block->offset, size, 0xff);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001197
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001198 //qemu_ram_setup_dump(new_block->host, size);
1199 //qemu_madvise(new_block->host, size, QEMU_MADV_HUGEPAGE);
1200 //qemu_madvise(new_block->host, size, QEMU_MADV_DONTFORK);
1201
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001202 if (kvm_enabled())
1203 kvm_setup_guest_memory(new_block->host, size);
1204
1205 return new_block->offset;
1206}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001207
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001208ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
1209{
1210 return qemu_ram_alloc_from_ptr(dev, name, size, NULL);
1211}
1212
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001213void qemu_ram_free_from_ptr(ram_addr_t addr)
1214{
1215 RAMBlock *block;
1216
1217 /* This assumes the iothread lock is taken here too. */
1218 qemu_mutex_lock_ramlist();
1219 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1220 if (addr == block->offset) {
1221 QTAILQ_REMOVE(&ram_list.blocks, block, next);
1222 ram_list.mru_block = NULL;
1223 ram_list.version++;
1224 g_free(block);
1225 break;
1226 }
1227 }
1228 qemu_mutex_unlock_ramlist();
1229}
1230
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001231void qemu_ram_free(ram_addr_t addr)
1232{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001233 RAMBlock *block;
1234
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001235 /* This assumes the iothread lock is taken here too. */
1236 qemu_mutex_lock_ramlist();
1237 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001238 if (addr == block->offset) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001239 QTAILQ_REMOVE(&ram_list.blocks, block, next);
1240 ram_list.mru_block = NULL;
1241 ram_list.version++;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001242 if (block->flags & RAM_PREALLOC_MASK) {
1243 ;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001244 } else if (xen_enabled()) {
1245 //xen_invalidate_map_cache_entry(block->host);
1246#ifndef _WIN32
1247 } else if (block->fd >= 0) {
1248 munmap(block->host, block->length);
1249 close(block->fd);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001250#endif
1251 } else {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001252 qemu_anon_ram_free(block->host, block->length);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001253 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001254 g_free(block);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001255 break;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001256 }
1257 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001258 qemu_mutex_unlock_ramlist();
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001259
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001260}
1261
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001262#ifndef _WIN32
1263void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
1264{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001265 RAMBlock *block;
1266 ram_addr_t offset;
1267 int flags;
1268 void *area, *vaddr;
1269
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001270 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001271 offset = addr - block->offset;
1272 if (offset < block->length) {
1273 vaddr = block->host + offset;
1274 if (block->flags & RAM_PREALLOC_MASK) {
1275 ;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001276 } else if (xen_enabled()) {
1277 abort();
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001278 } else {
1279 flags = MAP_FIXED;
1280 munmap(vaddr, length);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001281 if (block->fd >= 0) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001282#ifdef MAP_POPULATE
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001283 flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
1284 MAP_PRIVATE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001285#else
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001286 flags |= MAP_PRIVATE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001287#endif
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001288 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
1289 flags, block->fd, offset);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001290 } else {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001291 /*
1292 * Remap needs to match alloc. Accelerators that
1293 * set phys_mem_alloc never remap. If they did,
1294 * we'd need a remap hook here.
1295 */
1296 assert(phys_mem_alloc == qemu_anon_ram_alloc);
1297
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001298 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
1299 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
1300 flags, -1, 0);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001301 }
1302 if (area != vaddr) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001303 fprintf(stderr, "Could not remap addr: "
1304 RAM_ADDR_FMT "@" RAM_ADDR_FMT "\n",
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001305 length, addr);
1306 exit(1);
1307 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001308 memory_try_enable_merging(vaddr, length);
1309 qemu_ram_setup_dump(vaddr, length);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001310 }
1311 return;
1312 }
1313 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001314}
1315#endif /* !_WIN32 */
1316
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001317/* Return a host pointer to ram allocated with qemu_ram_alloc.
1318 With the exception of the softmmu code in this file, this should
1319 only be used for local memory (e.g. video ram) that the device owns,
1320 and knows it isn't going to access beyond the end of the block.
1321
1322 It should not be used for general purpose DMA.
1323 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
1324 */
1325void *qemu_get_ram_ptr(ram_addr_t addr)
1326{
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001327 RAMBlock *block = qemu_get_ram_block(addr);
1328#if 0
1329 if (xen_enabled()) {
1330 /* We need to check if the requested address is in the RAM
1331 * because we don't want to map the entire memory in QEMU.
1332 * In that case just map until the end of the page.
1333 */
1334 if (block->offset == 0) {
1335 return xen_map_cache(addr, 0, 0);
1336 } else if (block->host == NULL) {
1337 block->host =
1338 xen_map_cache(block->offset, block->length, 1);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001339 }
1340 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001341#endif
1342 return block->host + (addr - block->offset);
1343}
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001344
1345/* Return a host pointer to ram allocated with qemu_ram_alloc.
1346 * Same as qemu_get_ram_ptr but avoid reordering ramblocks.
1347 */
1348void *qemu_safe_ram_ptr(ram_addr_t addr)
1349{
1350 RAMBlock *block;
1351
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001352 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001353 if (addr - block->offset < block->length) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001354 return block->host + (addr - block->offset);
1355 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001356 }
1357
1358 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
1359 abort();
1360
1361 return NULL;
1362}
1363
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001364/* Some of the softmmu routines need to translate from a host pointer
1365 (typically a TLB entry) back to a ram offset. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001366int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
1367{
1368 RAMBlock *block;
1369 uint8_t *host = ptr;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001370#if 0
1371 if (xen_enabled()) {
1372 *ram_addr = xen_ram_addr_from_mapcache(ptr);
1373 return qemu_get_ram_block(*ram_addr)->mr;
1374 }
1375#endif
1376 block = ram_list.mru_block;
1377 if (block && block->host && host - block->host < block->length) {
1378 goto found;
1379 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001380
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001381 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1382 /* This case append when the block is not mapped. */
1383 if (block->host == NULL) {
1384 continue;
1385 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001386 if (host - block->host < block->length) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001387 goto found;
1388 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001389 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001390
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001391 return -1;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001392
1393found:
1394 *ram_addr = block->offset + (host - block->host);
1395 return 0;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001396}
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001397
1398/* Some of the softmmu routines need to translate from a host pointer
1399 (typically a TLB entry) back to a ram offset. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001400ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001401{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001402 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001403
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001404 if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001405 fprintf(stderr, "Bad ram pointer %p\n", ptr);
1406 abort();
1407 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001408 return ram_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001409}
1410
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001411static uint32_t unassigned_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001412{
1413#ifdef DEBUG_UNASSIGNED
1414 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
1415#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001416#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001417 do_unassigned_access(addr, 0, 0, 0, 1);
1418#endif
1419 return 0;
1420}
1421
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001422static uint32_t unassigned_mem_readw(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001423{
1424#ifdef DEBUG_UNASSIGNED
1425 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
1426#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001427#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001428 do_unassigned_access(addr, 0, 0, 0, 2);
1429#endif
1430 return 0;
1431}
1432
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001433static uint32_t unassigned_mem_readl(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001434{
1435#ifdef DEBUG_UNASSIGNED
1436 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
1437#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001438#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001439 do_unassigned_access(addr, 0, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001440#endif
1441 return 0;
1442}
1443
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001444static void unassigned_mem_writeb(void *opaque, hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001445{
1446#ifdef DEBUG_UNASSIGNED
1447 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
1448#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001449#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001450 do_unassigned_access(addr, 1, 0, 0, 1);
1451#endif
1452}
1453
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001454static void unassigned_mem_writew(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001455{
1456#ifdef DEBUG_UNASSIGNED
1457 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
1458#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001459#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001460 do_unassigned_access(addr, 1, 0, 0, 2);
1461#endif
1462}
1463
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001464static void unassigned_mem_writel(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001465{
1466#ifdef DEBUG_UNASSIGNED
1467 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
1468#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001469#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001470 do_unassigned_access(addr, 1, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001471#endif
1472}
1473
David 'Digit' Turner36411062010-12-22 17:34:53 +01001474static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001475 unassigned_mem_readb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001476 unassigned_mem_readw,
1477 unassigned_mem_readl,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001478};
1479
David 'Digit' Turner36411062010-12-22 17:34:53 +01001480static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001481 unassigned_mem_writeb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001482 unassigned_mem_writew,
1483 unassigned_mem_writel,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001484};
1485
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001486static void notdirty_mem_writeb(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001487 uint32_t val)
1488{
1489 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001490 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001491 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
1492#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turnerff9a2b82014-02-17 22:31:24 +01001493 tb_invalidate_phys_page_fast0(ram_addr, 1);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001494 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001495#endif
1496 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001497 stb_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001498 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001499 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001500 /* we remove the notdirty callback only if the code has been
1501 flushed */
1502 if (dirty_flags == 0xff)
1503 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
1504}
1505
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001506static void notdirty_mem_writew(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001507 uint32_t val)
1508{
1509 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001510 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001511 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
1512#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turnerff9a2b82014-02-17 22:31:24 +01001513 tb_invalidate_phys_page_fast0(ram_addr, 2);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001514 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001515#endif
1516 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001517 stw_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001518 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001519 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001520 /* we remove the notdirty callback only if the code has been
1521 flushed */
1522 if (dirty_flags == 0xff)
1523 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
1524}
1525
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001526static void notdirty_mem_writel(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001527 uint32_t val)
1528{
1529 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001530 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001531 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
1532#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turnerff9a2b82014-02-17 22:31:24 +01001533 tb_invalidate_phys_page_fast0(ram_addr, 4);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001534 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001535#endif
1536 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001537 stl_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001538 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001539 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001540 /* we remove the notdirty callback only if the code has been
1541 flushed */
1542 if (dirty_flags == 0xff)
1543 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
1544}
1545
David 'Digit' Turner36411062010-12-22 17:34:53 +01001546static CPUReadMemoryFunc * const error_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001547 NULL, /* never used */
1548 NULL, /* never used */
1549 NULL, /* never used */
1550};
1551
David 'Digit' Turner36411062010-12-22 17:34:53 +01001552static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001553 notdirty_mem_writeb,
1554 notdirty_mem_writew,
1555 notdirty_mem_writel,
1556};
1557
1558/* Generate a debug exception if a watchpoint has been hit. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001559static void check_watchpoint(int offset, int len_mask, int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001560{
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001561 CPUArchState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001562 target_ulong pc, cs_base;
1563 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001564 target_ulong vaddr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001565 CPUWatchpoint *wp;
1566 int cpu_flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001567
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001568 if (env->watchpoint_hit) {
1569 /* We re-entered the check after replacing the TB. Now raise
1570 * the debug interrupt so that is will trigger after the
1571 * current instruction. */
1572 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
1573 return;
1574 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001575 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001576 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001577 if ((vaddr == (wp->vaddr & len_mask) ||
1578 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
1579 wp->flags |= BP_WATCHPOINT_HIT;
1580 if (!env->watchpoint_hit) {
1581 env->watchpoint_hit = wp;
1582 tb = tb_find_pc(env->mem_io_pc);
1583 if (!tb) {
1584 cpu_abort(env, "check_watchpoint: could not find TB for "
1585 "pc=%p", (void *)env->mem_io_pc);
1586 }
David 'Digit' Turner3e0677d2014-03-07 15:01:06 +01001587 cpu_restore_state(env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001588 tb_phys_invalidate(tb, -1);
1589 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
1590 env->exception_index = EXCP_DEBUG;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001591 cpu_loop_exit(env);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001592 } else {
1593 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
1594 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001595 cpu_resume_from_signal(env, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001596 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001597 }
1598 } else {
1599 wp->flags &= ~BP_WATCHPOINT_HIT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001600 }
1601 }
1602}
1603
1604/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
1605 so these check for a hit then pass through to the normal out-of-line
1606 phys routines. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001607static uint32_t watch_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001608{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001609 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001610 return ldub_phys(addr);
1611}
1612
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001613static uint32_t watch_mem_readw(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001614{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001615 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001616 return lduw_phys(addr);
1617}
1618
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001619static uint32_t watch_mem_readl(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001620{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001621 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001622 return ldl_phys(addr);
1623}
1624
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001625static void watch_mem_writeb(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001626 uint32_t val)
1627{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001628 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001629 stb_phys(addr, val);
1630}
1631
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001632static void watch_mem_writew(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001633 uint32_t val)
1634{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001635 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001636 stw_phys(addr, val);
1637}
1638
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001639static void watch_mem_writel(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001640 uint32_t val)
1641{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001642 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001643 stl_phys(addr, val);
1644}
1645
David 'Digit' Turner36411062010-12-22 17:34:53 +01001646static CPUReadMemoryFunc * const watch_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001647 watch_mem_readb,
1648 watch_mem_readw,
1649 watch_mem_readl,
1650};
1651
David 'Digit' Turner36411062010-12-22 17:34:53 +01001652static CPUWriteMemoryFunc * const watch_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001653 watch_mem_writeb,
1654 watch_mem_writew,
1655 watch_mem_writel,
1656};
1657
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001658static inline uint32_t subpage_readlen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001659 unsigned int len)
1660{
1661 uint32_t ret;
1662 unsigned int idx;
1663
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001664 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001665#if defined(DEBUG_SUBPAGE)
1666 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
1667 mmio, len, addr, idx);
1668#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001669 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
1670 addr + mmio->region_offset[idx][0][len]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001671
1672 return ret;
1673}
1674
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001675static inline void subpage_writelen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001676 uint32_t value, unsigned int len)
1677{
1678 unsigned int idx;
1679
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001680 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001681#if defined(DEBUG_SUBPAGE)
1682 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
1683 mmio, len, addr, idx, value);
1684#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001685 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
1686 addr + mmio->region_offset[idx][1][len],
1687 value);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001688}
1689
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001690static uint32_t subpage_readb (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001691{
1692#if defined(DEBUG_SUBPAGE)
1693 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1694#endif
1695
1696 return subpage_readlen(opaque, addr, 0);
1697}
1698
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001699static void subpage_writeb (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001700 uint32_t value)
1701{
1702#if defined(DEBUG_SUBPAGE)
1703 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
1704#endif
1705 subpage_writelen(opaque, addr, value, 0);
1706}
1707
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001708static uint32_t subpage_readw (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001709{
1710#if defined(DEBUG_SUBPAGE)
1711 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1712#endif
1713
1714 return subpage_readlen(opaque, addr, 1);
1715}
1716
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001717static void subpage_writew (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001718 uint32_t value)
1719{
1720#if defined(DEBUG_SUBPAGE)
1721 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
1722#endif
1723 subpage_writelen(opaque, addr, value, 1);
1724}
1725
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001726static uint32_t subpage_readl (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001727{
1728#if defined(DEBUG_SUBPAGE)
1729 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
1730#endif
1731
1732 return subpage_readlen(opaque, addr, 2);
1733}
1734
1735static void subpage_writel (void *opaque,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001736 hwaddr addr, uint32_t value)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001737{
1738#if defined(DEBUG_SUBPAGE)
1739 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
1740#endif
1741 subpage_writelen(opaque, addr, value, 2);
1742}
1743
David 'Digit' Turner36411062010-12-22 17:34:53 +01001744static CPUReadMemoryFunc * const subpage_read[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001745 &subpage_readb,
1746 &subpage_readw,
1747 &subpage_readl,
1748};
1749
David 'Digit' Turner36411062010-12-22 17:34:53 +01001750static CPUWriteMemoryFunc * const subpage_write[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001751 &subpage_writeb,
1752 &subpage_writew,
1753 &subpage_writel,
1754};
1755
1756static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001757 ram_addr_t memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001758{
1759 int idx, eidx;
1760 unsigned int i;
1761
1762 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
1763 return -1;
1764 idx = SUBPAGE_IDX(start);
1765 eidx = SUBPAGE_IDX(end);
1766#if defined(DEBUG_SUBPAGE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001767 printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001768 mmio, start, end, idx, eidx, memory);
1769#endif
1770 memory >>= IO_MEM_SHIFT;
1771 for (; idx <= eidx; idx++) {
1772 for (i = 0; i < 4; i++) {
1773 if (io_mem_read[memory][i]) {
1774 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
1775 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001776 mmio->region_offset[idx][0][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001777 }
1778 if (io_mem_write[memory][i]) {
1779 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
1780 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001781 mmio->region_offset[idx][1][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001782 }
1783 }
1784 }
1785
1786 return 0;
1787}
1788
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001789static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001790 ram_addr_t orig_memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001791{
1792 subpage_t *mmio;
1793 int subpage_memory;
1794
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001795 mmio = g_malloc0(sizeof(subpage_t));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001796
1797 mmio->base = base;
1798 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001799#if defined(DEBUG_SUBPAGE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001800 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
1801 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001802#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001803 *phys = subpage_memory | IO_MEM_SUBPAGE;
1804 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
1805 region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001806
1807 return mmio;
1808}
1809
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001810static int get_free_io_mem_idx(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001811{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001812 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001813
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001814 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
1815 if (!io_mem_used[i]) {
1816 io_mem_used[i] = 1;
1817 return i;
1818 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001819 fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001820 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001821}
1822
1823/* mem_read and mem_write are arrays of functions containing the
1824 function to access byte (index 0), word (index 1) and dword (index
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001825 2). Functions can be omitted with a NULL function pointer.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001826 If io_index is non zero, the corresponding io zone is
1827 modified. If it is zero, a new io zone is allocated. The return
1828 value can be used with cpu_register_physical_memory(). (-1) is
1829 returned if error. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001830static int cpu_register_io_memory_fixed(int io_index,
David 'Digit' Turner36411062010-12-22 17:34:53 +01001831 CPUReadMemoryFunc * const *mem_read,
1832 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001833 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001834{
1835 int i, subwidth = 0;
1836
1837 if (io_index <= 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001838 io_index = get_free_io_mem_idx();
1839 if (io_index == -1)
1840 return io_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001841 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001842 io_index >>= IO_MEM_SHIFT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001843 if (io_index >= IO_MEM_NB_ENTRIES)
1844 return -1;
1845 }
1846
1847 for(i = 0;i < 3; i++) {
1848 if (!mem_read[i] || !mem_write[i])
1849 subwidth = IO_MEM_SUBWIDTH;
1850 io_mem_read[io_index][i] = mem_read[i];
1851 io_mem_write[io_index][i] = mem_write[i];
1852 }
1853 io_mem_opaque[io_index] = opaque;
1854 return (io_index << IO_MEM_SHIFT) | subwidth;
1855}
1856
David 'Digit' Turner36411062010-12-22 17:34:53 +01001857int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
1858 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001859 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001860{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001861 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001862}
1863
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001864void cpu_unregister_io_memory(int io_table_address)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001865{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001866 int i;
1867 int io_index = io_table_address >> IO_MEM_SHIFT;
1868
1869 for (i=0;i < 3; i++) {
1870 io_mem_read[io_index][i] = unassigned_mem_read[i];
1871 io_mem_write[io_index][i] = unassigned_mem_write[i];
1872 }
1873 io_mem_opaque[io_index] = NULL;
1874 io_mem_used[io_index] = 0;
1875}
1876
1877static void io_mem_init(void)
1878{
1879 int i;
1880
1881 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
1882 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
1883 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
1884 for (i=0; i<5; i++)
1885 io_mem_used[i] = 1;
1886
1887 io_mem_watch = cpu_register_io_memory(watch_mem_read,
1888 watch_mem_write, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001889}
1890
1891#endif /* !defined(CONFIG_USER_ONLY) */
1892
1893/* physical memory access (slow version, mainly for debug) */
1894#if defined(CONFIG_USER_ONLY)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001895void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001896 int len, int is_write)
1897{
1898 int l, flags;
1899 target_ulong page;
1900 void * p;
1901
1902 while (len > 0) {
1903 page = addr & TARGET_PAGE_MASK;
1904 l = (page + TARGET_PAGE_SIZE) - addr;
1905 if (l > len)
1906 l = len;
1907 flags = page_get_flags(page);
1908 if (!(flags & PAGE_VALID))
1909 return;
1910 if (is_write) {
1911 if (!(flags & PAGE_WRITE))
1912 return;
1913 /* XXX: this code should not depend on lock_user */
1914 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
1915 /* FIXME - should this return an error rather than just fail? */
1916 return;
1917 memcpy(p, buf, l);
1918 unlock_user(p, addr, l);
1919 } else {
1920 if (!(flags & PAGE_READ))
1921 return;
1922 /* XXX: this code should not depend on lock_user */
1923 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
1924 /* FIXME - should this return an error rather than just fail? */
1925 return;
1926 memcpy(buf, p, l);
1927 unlock_user(p, addr, 0);
1928 }
1929 len -= l;
1930 buf += l;
1931 addr += l;
1932 }
1933}
1934
1935#else
Pete Delaneyd09d7662013-03-28 19:53:13 -07001936
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001937static void invalidate_and_set_dirty(hwaddr addr,
1938 hwaddr length)
Pete Delaneyd09d7662013-03-28 19:53:13 -07001939{
1940 if (!cpu_physical_memory_is_dirty(addr)) {
1941 /* invalidate code */
1942 tb_invalidate_phys_page_range(addr, addr + length, 0);
1943 /* set dirty bit */
1944 cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG));
1945 }
1946}
1947
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001948void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001949 int len, int is_write)
1950{
1951 int l, io_index;
1952 uint8_t *ptr;
1953 uint32_t val;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001954 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001955 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001956 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001957 PhysPageDesc *p;
1958
1959 while (len > 0) {
1960 page = addr & TARGET_PAGE_MASK;
1961 l = (page + TARGET_PAGE_SIZE) - addr;
1962 if (l > len)
1963 l = len;
1964 p = phys_page_find(page >> TARGET_PAGE_BITS);
1965 if (!p) {
1966 pd = IO_MEM_UNASSIGNED;
1967 } else {
1968 pd = p->phys_offset;
1969 }
1970
1971 if (is_write) {
1972 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001973 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001974 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001975 if (p)
1976 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001977 /* XXX: could force cpu_single_env to NULL to avoid
1978 potential bugs */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001979 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001980 /* 32 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001981 val = ldl_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001982 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001983 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001984 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001985 /* 16 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001986 val = lduw_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001987 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001988 l = 2;
1989 } else {
1990 /* 8 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01001991 val = ldub_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001992 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001993 l = 1;
1994 }
1995 } else {
1996 unsigned long addr1;
1997 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
1998 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001999 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002000 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07002001 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002002 }
2003 } else {
2004 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2005 !(pd & IO_MEM_ROMD)) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002006 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002007 /* I/O case */
2008 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002009 if (p)
2010 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
2011 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002012 /* 32 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002013 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002014 stl_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002015 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002016 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002017 /* 16 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002018 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002019 stw_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002020 l = 2;
2021 } else {
2022 /* 8 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002023 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002024 stb_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002025 l = 1;
2026 }
2027 } else {
2028 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002029 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002030 (addr & ~TARGET_PAGE_MASK);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002031 memcpy(buf8, ptr, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002032 }
2033 }
2034 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002035 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002036 addr += l;
2037 }
2038}
2039
2040/* used for ROM loading : can write in RAM and ROM */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002041void cpu_physical_memory_write_rom(hwaddr addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002042 const void *buf, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002043{
2044 int l;
2045 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002046 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002047 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002048 const uint8_t* buf8 = (const uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002049 PhysPageDesc *p;
2050
2051 while (len > 0) {
2052 page = addr & TARGET_PAGE_MASK;
2053 l = (page + TARGET_PAGE_SIZE) - addr;
2054 if (l > len)
2055 l = len;
2056 p = phys_page_find(page >> TARGET_PAGE_BITS);
2057 if (!p) {
2058 pd = IO_MEM_UNASSIGNED;
2059 } else {
2060 pd = p->phys_offset;
2061 }
2062
2063 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
2064 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
2065 !(pd & IO_MEM_ROMD)) {
2066 /* do nothing */
2067 } else {
2068 unsigned long addr1;
2069 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2070 /* ROM/RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002071 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002072 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07002073 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002074 }
2075 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002076 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002077 addr += l;
2078 }
2079}
2080
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002081typedef struct {
2082 void *buffer;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002083 hwaddr addr;
2084 hwaddr len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002085} BounceBuffer;
2086
2087static BounceBuffer bounce;
2088
2089typedef struct MapClient {
2090 void *opaque;
2091 void (*callback)(void *opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002092 QLIST_ENTRY(MapClient) link;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002093} MapClient;
2094
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002095static QLIST_HEAD(map_client_list, MapClient) map_client_list
2096 = QLIST_HEAD_INITIALIZER(map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002097
2098void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
2099{
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002100 MapClient *client = g_malloc(sizeof(*client));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002101
2102 client->opaque = opaque;
2103 client->callback = callback;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002104 QLIST_INSERT_HEAD(&map_client_list, client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002105 return client;
2106}
2107
2108void cpu_unregister_map_client(void *_client)
2109{
2110 MapClient *client = (MapClient *)_client;
2111
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002112 QLIST_REMOVE(client, link);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002113 g_free(client);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002114}
2115
2116static void cpu_notify_map_clients(void)
2117{
2118 MapClient *client;
2119
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002120 while (!QLIST_EMPTY(&map_client_list)) {
2121 client = QLIST_FIRST(&map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002122 client->callback(client->opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002123 QLIST_REMOVE(client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002124 }
2125}
2126
2127/* Map a physical memory region into a host virtual address.
2128 * May map a subset of the requested range, given by and returned in *plen.
2129 * May return NULL if resources needed to perform the mapping are exhausted.
2130 * Use only for reads OR writes - not for read-modify-write operations.
2131 * Use cpu_register_map_client() to know when retrying the map operation is
2132 * likely to succeed.
2133 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002134void *cpu_physical_memory_map(hwaddr addr,
2135 hwaddr *plen,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002136 int is_write)
2137{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002138 hwaddr len = *plen;
2139 hwaddr done = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002140 int l;
2141 uint8_t *ret = NULL;
2142 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002143 hwaddr page;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002144 unsigned long pd;
2145 PhysPageDesc *p;
2146 unsigned long addr1;
2147
2148 while (len > 0) {
2149 page = addr & TARGET_PAGE_MASK;
2150 l = (page + TARGET_PAGE_SIZE) - addr;
2151 if (l > len)
2152 l = len;
2153 p = phys_page_find(page >> TARGET_PAGE_BITS);
2154 if (!p) {
2155 pd = IO_MEM_UNASSIGNED;
2156 } else {
2157 pd = p->phys_offset;
2158 }
2159
2160 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2161 if (done || bounce.buffer) {
2162 break;
2163 }
2164 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
2165 bounce.addr = addr;
2166 bounce.len = l;
2167 if (!is_write) {
2168 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
2169 }
2170 ptr = bounce.buffer;
2171 } else {
2172 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2173 ptr = qemu_get_ram_ptr(addr1);
2174 }
2175 if (!done) {
2176 ret = ptr;
2177 } else if (ret + done != ptr) {
2178 break;
2179 }
2180
2181 len -= l;
2182 addr += l;
2183 done += l;
2184 }
2185 *plen = done;
2186 return ret;
2187}
2188
2189/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
2190 * Will also mark the memory as dirty if is_write == 1. access_len gives
2191 * the amount of memory that was actually read or written by the caller.
2192 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002193void cpu_physical_memory_unmap(void *buffer, hwaddr len,
2194 int is_write, hwaddr access_len)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002195{
2196 if (buffer != bounce.buffer) {
2197 if (is_write) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002198 ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002199 while (access_len) {
2200 unsigned l;
2201 l = TARGET_PAGE_SIZE;
2202 if (l > access_len)
2203 l = access_len;
Pete Delaneyd09d7662013-03-28 19:53:13 -07002204 invalidate_and_set_dirty(addr1, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002205 addr1 += l;
2206 access_len -= l;
2207 }
2208 }
2209 return;
2210 }
2211 if (is_write) {
2212 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
2213 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002214 qemu_vfree(bounce.buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002215 bounce.buffer = NULL;
2216 cpu_notify_map_clients();
2217}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002218
2219/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002220uint32_t ldl_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002221{
2222 int io_index;
2223 uint8_t *ptr;
2224 uint32_t val;
2225 unsigned long pd;
2226 PhysPageDesc *p;
2227
2228 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2229 if (!p) {
2230 pd = IO_MEM_UNASSIGNED;
2231 } else {
2232 pd = p->phys_offset;
2233 }
2234
2235 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2236 !(pd & IO_MEM_ROMD)) {
2237 /* I/O case */
2238 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002239 if (p)
2240 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002241 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2242 } else {
2243 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002244 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002245 (addr & ~TARGET_PAGE_MASK);
2246 val = ldl_p(ptr);
2247 }
2248 return val;
2249}
2250
2251/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002252uint64_t ldq_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002253{
2254 int io_index;
2255 uint8_t *ptr;
2256 uint64_t val;
2257 unsigned long pd;
2258 PhysPageDesc *p;
2259
2260 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2261 if (!p) {
2262 pd = IO_MEM_UNASSIGNED;
2263 } else {
2264 pd = p->phys_offset;
2265 }
2266
2267 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2268 !(pd & IO_MEM_ROMD)) {
2269 /* I/O case */
2270 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002271 if (p)
2272 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002273#ifdef TARGET_WORDS_BIGENDIAN
2274 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
2275 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
2276#else
2277 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2278 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
2279#endif
2280 } else {
2281 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002282 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002283 (addr & ~TARGET_PAGE_MASK);
2284 val = ldq_p(ptr);
2285 }
2286 return val;
2287}
2288
2289/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002290uint32_t ldub_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002291{
2292 uint8_t val;
2293 cpu_physical_memory_read(addr, &val, 1);
2294 return val;
2295}
2296
2297/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002298uint32_t lduw_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002299{
2300 uint16_t val;
2301 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
2302 return tswap16(val);
2303}
2304
2305/* warning: addr must be aligned. The ram page is not masked as dirty
2306 and the code inside is not invalidated. It is useful if the dirty
2307 bits are used to track modified PTEs */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002308void stl_phys_notdirty(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002309{
2310 int io_index;
2311 uint8_t *ptr;
2312 unsigned long pd;
2313 PhysPageDesc *p;
2314
2315 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2316 if (!p) {
2317 pd = IO_MEM_UNASSIGNED;
2318 } else {
2319 pd = p->phys_offset;
2320 }
2321
2322 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2323 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002324 if (p)
2325 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002326 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2327 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002328 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2329 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002330 stl_p(ptr, val);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002331
2332 if (unlikely(in_migration)) {
2333 if (!cpu_physical_memory_is_dirty(addr1)) {
2334 /* invalidate code */
2335 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
2336 /* set dirty bit */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002337 cpu_physical_memory_set_dirty_flags(
2338 addr1, (0xff & ~CODE_DIRTY_FLAG));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002339 }
2340 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002341 }
2342}
2343
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002344void stq_phys_notdirty(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002345{
2346 int io_index;
2347 uint8_t *ptr;
2348 unsigned long pd;
2349 PhysPageDesc *p;
2350
2351 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2352 if (!p) {
2353 pd = IO_MEM_UNASSIGNED;
2354 } else {
2355 pd = p->phys_offset;
2356 }
2357
2358 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2359 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002360 if (p)
2361 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002362#ifdef TARGET_WORDS_BIGENDIAN
2363 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
2364 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
2365#else
2366 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2367 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
2368#endif
2369 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002370 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002371 (addr & ~TARGET_PAGE_MASK);
2372 stq_p(ptr, val);
2373 }
2374}
2375
2376/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002377void stl_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002378{
2379 int io_index;
2380 uint8_t *ptr;
2381 unsigned long pd;
2382 PhysPageDesc *p;
2383
2384 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2385 if (!p) {
2386 pd = IO_MEM_UNASSIGNED;
2387 } else {
2388 pd = p->phys_offset;
2389 }
2390
2391 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2392 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002393 if (p)
2394 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002395 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2396 } else {
2397 unsigned long addr1;
2398 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2399 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002400 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002401 stl_p(ptr, val);
Pete Delaneyd09d7662013-03-28 19:53:13 -07002402 invalidate_and_set_dirty(addr1, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002403 }
2404}
2405
2406/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002407void stb_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002408{
2409 uint8_t v = val;
2410 cpu_physical_memory_write(addr, &v, 1);
2411}
2412
2413/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002414void stw_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002415{
2416 uint16_t v = tswap16(val);
2417 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
2418}
2419
2420/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002421void stq_phys(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002422{
2423 val = tswap64(val);
2424 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
2425}
2426
2427#endif
2428
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002429/* virtual memory access for debug (includes writing to ROM) */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002430int cpu_memory_rw_debug(CPUOldState *env, target_ulong addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002431 void *buf, int len, int is_write)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002432{
2433 int l;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002434 hwaddr phys_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002435 target_ulong page;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002436 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002437
2438 while (len > 0) {
2439 page = addr & TARGET_PAGE_MASK;
2440 phys_addr = cpu_get_phys_page_debug(env, page);
2441 /* if no physical page mapped, return an error */
2442 if (phys_addr == -1)
2443 return -1;
2444 l = (page + TARGET_PAGE_SIZE) - addr;
2445 if (l > len)
2446 l = len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002447 phys_addr += (addr & ~TARGET_PAGE_MASK);
2448#if !defined(CONFIG_USER_ONLY)
2449 if (is_write)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002450 cpu_physical_memory_write_rom(phys_addr, buf8, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002451 else
2452#endif
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002453 cpu_physical_memory_rw(phys_addr, buf8, l, is_write);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002454 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002455 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002456 addr += l;
2457 }
2458 return 0;
2459}