exec.c 73.0 KB
Newer Older
B
bellard 已提交
1
/*
2
 *  Virtual page mapping
3
 *
B
bellard 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16
 *  Copyright (c) 2003 Fabrice Bellard
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
B
bellard 已提交
18
 */
B
bellard 已提交
19
#include "config.h"
B
bellard 已提交
20 21 22
#ifdef _WIN32
#include <windows.h>
#else
B
bellard 已提交
23
#include <sys/types.h>
B
bellard 已提交
24 25
#include <sys/mman.h>
#endif
B
bellard 已提交
26

27
#include "qemu-common.h"
B
bellard 已提交
28
#include "cpu.h"
B
bellard 已提交
29
#include "tcg.h"
30
#include "hw/hw.h"
31
#include "hw/qdev.h"
32
#include "qemu/osdep.h"
33
#include "sysemu/kvm.h"
P
Paolo Bonzini 已提交
34
#include "hw/xen/xen.h"
35 36
#include "qemu/timer.h"
#include "qemu/config-file.h"
37
#include "exec/memory.h"
38
#include "sysemu/dma.h"
39
#include "exec/address-spaces.h"
40 41
#if defined(CONFIG_USER_ONLY)
#include <qemu.h>
J
Jun Nakajima 已提交
42
#else /* !CONFIG_USER_ONLY */
43
#include "sysemu/xen-mapcache.h"
44
#include "trace.h"
45
#endif
46
#include "exec/cpu-all.h"
B
bellard 已提交
47

48
#include "exec/cputlb.h"
49
#include "translate-all.h"
50

51
#include "exec/memory-internal.h"
52

P
pbrook 已提交
53
//#define DEBUG_UNASSIGNED
54
//#define DEBUG_SUBPAGE
T
ths 已提交
55

56
#if !defined(CONFIG_USER_ONLY)
57
int phys_ram_fd;
A
aliguori 已提交
58
static int in_migration;
P
pbrook 已提交
59

P
Paolo Bonzini 已提交
60
RAMList ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) };
A
Avi Kivity 已提交
61 62

static MemoryRegion *system_memory;
63
static MemoryRegion *system_io;
A
Avi Kivity 已提交
64

65 66
AddressSpace address_space_io;
AddressSpace address_space_memory;
67
DMAContext dma_context_memory;
68

69
MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty;
70
static MemoryRegion io_mem_subpage_ram;
71

72
#endif
73

74
CPUArchState *first_cpu;
B
bellard 已提交
75 76
/* current CPU in the current thread. It is only valid inside
   cpu_exec() */
77
DEFINE_TLS(CPUArchState *,cpu_single_env);
P
pbrook 已提交
78
/* 0 = Do not count executed instructions.
T
ths 已提交
79
   1 = Precise instruction counting.
P
pbrook 已提交
80
   2 = Adaptive rate instruction counting.  */
81
int use_icount;
B
bellard 已提交
82

83
#if !defined(CONFIG_USER_ONLY)
84

85 86 87
static MemoryRegionSection *phys_sections;
static unsigned phys_sections_nb, phys_sections_nb_alloc;
static uint16_t phys_section_unassigned;
88 89 90
static uint16_t phys_section_notdirty;
static uint16_t phys_section_rom;
static uint16_t phys_section_watch;
91

92 93 94 95
/* Simple allocator for PhysPageEntry nodes */
static PhysPageEntry (*phys_map_nodes)[L2_SIZE];
static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc;

96
#define PHYS_MAP_NODE_NIL (((uint16_t)~0) >> 1)
97

98
static void io_mem_init(void);
A
Avi Kivity 已提交
99
static void memory_map_init(void);
B
Blue Swirl 已提交
100
static void *qemu_safe_ram_ptr(ram_addr_t addr);
101

102
static MemoryRegion io_mem_watch;
103
#endif
B
bellard 已提交
104

105
#if !defined(CONFIG_USER_ONLY)
106

107
static void phys_map_node_reserve(unsigned nodes)
108
{
109
    if (phys_map_nodes_nb + nodes > phys_map_nodes_nb_alloc) {
110 111
        typedef PhysPageEntry Node[L2_SIZE];
        phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc * 2, 16);
112 113
        phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc,
                                      phys_map_nodes_nb + nodes);
114 115 116
        phys_map_nodes = g_renew(Node, phys_map_nodes,
                                 phys_map_nodes_nb_alloc);
    }
117 118 119 120 121 122 123 124 125 126
}

static uint16_t phys_map_node_alloc(void)
{
    unsigned i;
    uint16_t ret;

    ret = phys_map_nodes_nb++;
    assert(ret != PHYS_MAP_NODE_NIL);
    assert(ret != phys_map_nodes_nb_alloc);
127
    for (i = 0; i < L2_SIZE; ++i) {
128
        phys_map_nodes[ret][i].is_leaf = 0;
129
        phys_map_nodes[ret][i].ptr = PHYS_MAP_NODE_NIL;
130
    }
131
    return ret;
132 133 134 135 136 137 138
}

static void phys_map_nodes_reset(void)
{
    phys_map_nodes_nb = 0;
}

B
bellard 已提交
139

A
Avi Kivity 已提交
140 141
static void phys_page_set_level(PhysPageEntry *lp, hwaddr *index,
                                hwaddr *nb, uint16_t leaf,
142
                                int level)
143 144 145
{
    PhysPageEntry *p;
    int i;
A
Avi Kivity 已提交
146
    hwaddr step = (hwaddr)1 << (level * L2_BITS);
147

148
    if (!lp->is_leaf && lp->ptr == PHYS_MAP_NODE_NIL) {
149 150
        lp->ptr = phys_map_node_alloc();
        p = phys_map_nodes[lp->ptr];
151 152
        if (level == 0) {
            for (i = 0; i < L2_SIZE; i++) {
153
                p[i].is_leaf = 1;
154
                p[i].ptr = phys_section_unassigned;
155
            }
P
pbrook 已提交
156
        }
157
    } else {
158
        p = phys_map_nodes[lp->ptr];
B
bellard 已提交
159
    }
160
    lp = &p[(*index >> (level * L2_BITS)) & (L2_SIZE - 1)];
161

162
    while (*nb && lp < &p[L2_SIZE]) {
163 164
        if ((*index & (step - 1)) == 0 && *nb >= step) {
            lp->is_leaf = true;
165
            lp->ptr = leaf;
166 167
            *index += step;
            *nb -= step;
168 169 170 171
        } else {
            phys_page_set_level(lp, index, nb, leaf, level - 1);
        }
        ++lp;
172 173 174
    }
}

A
Avi Kivity 已提交
175
static void phys_page_set(AddressSpaceDispatch *d,
A
Avi Kivity 已提交
176
                          hwaddr index, hwaddr nb,
177
                          uint16_t leaf)
178
{
179
    /* Wildly overreserve - it doesn't matter much. */
180
    phys_map_node_reserve(3 * P_L2_LEVELS);
181

A
Avi Kivity 已提交
182
    phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1);
B
bellard 已提交
183 184
}

A
Avi Kivity 已提交
185
MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
B
bellard 已提交
186
{
A
Avi Kivity 已提交
187
    PhysPageEntry lp = d->phys_map;
188 189 190
    PhysPageEntry *p;
    int i;
    uint16_t s_index = phys_section_unassigned;
191

192
    for (i = P_L2_LEVELS - 1; i >= 0 && !lp.is_leaf; i--) {
193
        if (lp.ptr == PHYS_MAP_NODE_NIL) {
194 195
            goto not_found;
        }
196
        p = phys_map_nodes[lp.ptr];
197
        lp = p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)];
198
    }
199

200
    s_index = lp.ptr;
201
not_found:
202 203 204
    return &phys_sections[s_index];
}

B
Blue Swirl 已提交
205 206 207 208
bool memory_region_is_unassigned(MemoryRegion *mr)
{
    return mr != &io_mem_ram && mr != &io_mem_rom
        && mr != &io_mem_notdirty && !mr->rom_device
209
        && mr != &io_mem_watch;
B
bellard 已提交
210
}
211
#endif
B
bellard 已提交
212

213
void cpu_exec_init_all(void)
214
{
215
#if !defined(CONFIG_USER_ONLY)
216
    qemu_mutex_init(&ram_list.mutex);
217 218
    memory_map_init();
    io_mem_init();
219
#endif
220
}
221

222
#if !defined(CONFIG_USER_ONLY)
223 224

static int cpu_common_post_load(void *opaque, int version_id)
B
bellard 已提交
225
{
226
    CPUState *cpu = opaque;
B
bellard 已提交
227

228 229
    /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
       version_id is increased. */
230 231
    cpu->interrupt_request &= ~0x01;
    tlb_flush(cpu->env_ptr, 1);
232 233

    return 0;
B
bellard 已提交
234
}
B
bellard 已提交
235

236 237 238 239 240 241 242
static const VMStateDescription vmstate_cpu_common = {
    .name = "cpu_common",
    .version_id = 1,
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .post_load = cpu_common_post_load,
    .fields      = (VMStateField []) {
243 244
        VMSTATE_UINT32(halted, CPUState),
        VMSTATE_UINT32(interrupt_request, CPUState),
245 246 247
        VMSTATE_END_OF_LIST()
    }
};
248 249
#else
#define vmstate_cpu_common vmstate_dummy
250
#endif
B
bellard 已提交
251

252
CPUState *qemu_get_cpu(int index)
B
bellard 已提交
253
{
254
    CPUArchState *env = first_cpu;
255
    CPUState *cpu = NULL;
B
bellard 已提交
256

257
    while (env) {
258 259
        cpu = ENV_GET_CPU(env);
        if (cpu->cpu_index == index) {
260
            break;
261
        }
262
        env = env->next_cpu;
B
bellard 已提交
263
    }
264

265
    return env ? cpu : NULL;
B
bellard 已提交
266 267
}

268 269 270 271 272 273 274 275 276 277
void qemu_for_each_cpu(void (*func)(CPUState *cpu, void *data), void *data)
{
    CPUArchState *env = first_cpu;

    while (env) {
        func(ENV_GET_CPU(env), data);
        env = env->next_cpu;
    }
}

278
void cpu_exec_init(CPUArchState *env)
B
bellard 已提交
279
{
280
    CPUState *cpu = ENV_GET_CPU(env);
281
    CPUClass *cc = CPU_GET_CLASS(cpu);
282 283 284 285 286 287 288 289 290 291 292 293 294
    CPUArchState **penv;
    int cpu_index;

#if defined(CONFIG_USER_ONLY)
    cpu_list_lock();
#endif
    env->next_cpu = NULL;
    penv = &first_cpu;
    cpu_index = 0;
    while (*penv != NULL) {
        penv = &(*penv)->next_cpu;
        cpu_index++;
    }
295
    cpu->cpu_index = cpu_index;
296
    cpu->numa_node = 0;
297 298 299 300 301 302 303 304 305
    QTAILQ_INIT(&env->breakpoints);
    QTAILQ_INIT(&env->watchpoints);
#ifndef CONFIG_USER_ONLY
    cpu->thread_id = qemu_get_thread_id();
#endif
    *penv = env;
#if defined(CONFIG_USER_ONLY)
    cpu_list_unlock();
#endif
306
    vmstate_register(NULL, cpu_index, &vmstate_cpu_common, cpu);
307 308 309
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
    register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
                    cpu_save, cpu_load, env);
310
    assert(cc->vmsd == NULL);
311
#endif
312 313 314
    if (cc->vmsd != NULL) {
        vmstate_register(NULL, cpu_index, cc->vmsd, cpu);
    }
B
bellard 已提交
315 316
}

B
bellard 已提交
317
#if defined(TARGET_HAS_ICE)
318
#if defined(CONFIG_USER_ONLY)
319
static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
320 321 322 323
{
    tb_invalidate_phys_page_range(pc, pc + 1, 0);
}
#else
324 325
static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
{
326 327
    tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc) |
            (pc & ~TARGET_PAGE_MASK));
328
}
B
bellard 已提交
329
#endif
330
#endif /* TARGET_HAS_ICE */
B
bellard 已提交
331

332
#if defined(CONFIG_USER_ONLY)
333
void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
334 335 336 337

{
}

338
int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
339 340 341 342 343
                          int flags, CPUWatchpoint **watchpoint)
{
    return -ENOSYS;
}
#else
344
/* Add a watchpoint.  */
345
int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
346
                          int flags, CPUWatchpoint **watchpoint)
347
{
348
    target_ulong len_mask = ~(len - 1);
349
    CPUWatchpoint *wp;
350

351
    /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
352 353
    if ((len & (len - 1)) || (addr & ~len_mask) ||
            len == 0 || len > TARGET_PAGE_SIZE) {
354 355 356 357
        fprintf(stderr, "qemu: tried to set invalid watchpoint at "
                TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
        return -EINVAL;
    }
358
    wp = g_malloc(sizeof(*wp));
359 360

    wp->vaddr = addr;
361
    wp->len_mask = len_mask;
362 363
    wp->flags = flags;

364
    /* keep all GDB-injected watchpoints in front */
365
    if (flags & BP_GDB)
B
Blue Swirl 已提交
366
        QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
367
    else
B
Blue Swirl 已提交
368
        QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
369 370

    tlb_flush_page(env, addr);
371 372 373 374

    if (watchpoint)
        *watchpoint = wp;
    return 0;
375 376
}

377
/* Remove a specific watchpoint.  */
378
int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
379
                          int flags)
380
{
381
    target_ulong len_mask = ~(len - 1);
382
    CPUWatchpoint *wp;
383

B
Blue Swirl 已提交
384
    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
385
        if (addr == wp->vaddr && len_mask == wp->len_mask
386
                && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
387
            cpu_watchpoint_remove_by_ref(env, wp);
388 389 390
            return 0;
        }
    }
391
    return -ENOENT;
392 393
}

394
/* Remove a specific watchpoint by reference.  */
395
void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
396
{
B
Blue Swirl 已提交
397
    QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
398

399 400
    tlb_flush_page(env, watchpoint->vaddr);

401
    g_free(watchpoint);
402 403 404
}

/* Remove all matching watchpoints.  */
405
void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
406
{
407
    CPUWatchpoint *wp, *next;
408

B
Blue Swirl 已提交
409
    QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
410 411
        if (wp->flags & mask)
            cpu_watchpoint_remove_by_ref(env, wp);
412
    }
413
}
414
#endif
415

416
/* Add a breakpoint.  */
417
int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
418
                          CPUBreakpoint **breakpoint)
B
bellard 已提交
419
{
B
bellard 已提交
420
#if defined(TARGET_HAS_ICE)
421
    CPUBreakpoint *bp;
422

423
    bp = g_malloc(sizeof(*bp));
B
bellard 已提交
424

425 426 427
    bp->pc = pc;
    bp->flags = flags;

428
    /* keep all GDB-injected breakpoints in front */
429
    if (flags & BP_GDB)
B
Blue Swirl 已提交
430
        QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
431
    else
B
Blue Swirl 已提交
432
        QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
433

B
bellard 已提交
434
    breakpoint_invalidate(env, pc);
435 436 437

    if (breakpoint)
        *breakpoint = bp;
B
bellard 已提交
438 439
    return 0;
#else
440
    return -ENOSYS;
B
bellard 已提交
441 442 443
#endif
}

444
/* Remove a specific breakpoint.  */
445
int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
446
{
447
#if defined(TARGET_HAS_ICE)
448 449
    CPUBreakpoint *bp;

B
Blue Swirl 已提交
450
    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
451 452 453 454
        if (bp->pc == pc && bp->flags == flags) {
            cpu_breakpoint_remove_by_ref(env, bp);
            return 0;
        }
455
    }
456 457 458
    return -ENOENT;
#else
    return -ENOSYS;
459 460 461
#endif
}

462
/* Remove a specific breakpoint by reference.  */
463
void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
B
bellard 已提交
464
{
B
bellard 已提交
465
#if defined(TARGET_HAS_ICE)
B
Blue Swirl 已提交
466
    QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
B
bellard 已提交
467

468 469
    breakpoint_invalidate(env, breakpoint->pc);

470
    g_free(breakpoint);
471 472 473 474
#endif
}

/* Remove all matching breakpoints. */
475
void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
476 477
{
#if defined(TARGET_HAS_ICE)
478
    CPUBreakpoint *bp, *next;
479

B
Blue Swirl 已提交
480
    QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
481 482
        if (bp->flags & mask)
            cpu_breakpoint_remove_by_ref(env, bp);
483
    }
B
bellard 已提交
484 485 486
#endif
}

B
bellard 已提交
487 488
/* enable or disable single step mode. EXCP_DEBUG is returned by the
   CPU loop after each instruction */
489
void cpu_single_step(CPUArchState *env, int enabled)
B
bellard 已提交
490
{
B
bellard 已提交
491
#if defined(TARGET_HAS_ICE)
B
bellard 已提交
492 493
    if (env->singlestep_enabled != enabled) {
        env->singlestep_enabled = enabled;
494 495 496
        if (kvm_enabled())
            kvm_update_guest_debug(env, 0);
        else {
S
Stuart Brady 已提交
497
            /* must flush all the translated code to avoid inconsistencies */
498 499 500
            /* XXX: only flush what is necessary */
            tb_flush(env);
        }
B
bellard 已提交
501 502 503 504
    }
#endif
}

505
void cpu_exit(CPUArchState *env)
506
{
507 508 509
    CPUState *cpu = ENV_GET_CPU(env);

    cpu->exit_request = 1;
510
    cpu->tcg_exit_req = 1;
511 512
}

513
void cpu_abort(CPUArchState *env, const char *fmt, ...)
B
bellard 已提交
514 515
{
    va_list ap;
P
pbrook 已提交
516
    va_list ap2;
B
bellard 已提交
517 518

    va_start(ap, fmt);
P
pbrook 已提交
519
    va_copy(ap2, ap);
B
bellard 已提交
520 521 522
    fprintf(stderr, "qemu: fatal: ");
    vfprintf(stderr, fmt, ap);
    fprintf(stderr, "\n");
523
    cpu_dump_state(env, stderr, fprintf, CPU_DUMP_FPU | CPU_DUMP_CCOP);
524 525 526 527
    if (qemu_log_enabled()) {
        qemu_log("qemu: fatal: ");
        qemu_log_vprintf(fmt, ap2);
        qemu_log("\n");
528
        log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP);
529
        qemu_log_flush();
530
        qemu_log_close();
531
    }
P
pbrook 已提交
532
    va_end(ap2);
533
    va_end(ap);
534 535 536 537 538 539 540 541
#if defined(CONFIG_USER_ONLY)
    {
        struct sigaction act;
        sigfillset(&act.sa_mask);
        act.sa_handler = SIG_DFL;
        sigaction(SIGABRT, &act, NULL);
    }
#endif
B
bellard 已提交
542 543 544
    abort();
}

545
CPUArchState *cpu_copy(CPUArchState *env)
546
{
547 548
    CPUArchState *new_env = cpu_init(env->cpu_model_str);
    CPUArchState *next_cpu = new_env->next_cpu;
549 550 551 552 553
#if defined(TARGET_HAS_ICE)
    CPUBreakpoint *bp;
    CPUWatchpoint *wp;
#endif

554
    memcpy(new_env, env, sizeof(CPUArchState));
555

556
    /* Preserve chaining. */
557
    new_env->next_cpu = next_cpu;
558 559 560 561

    /* Clone all break/watchpoints.
       Note: Once we support ptrace with hw-debug register access, make sure
       BP_CPU break/watchpoints are handled correctly on clone. */
B
Blue Swirl 已提交
562 563
    QTAILQ_INIT(&env->breakpoints);
    QTAILQ_INIT(&env->watchpoints);
564
#if defined(TARGET_HAS_ICE)
B
Blue Swirl 已提交
565
    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
566 567
        cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
    }
B
Blue Swirl 已提交
568
    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
569 570 571 572 573
        cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
                              wp->flags, NULL);
    }
#endif

574 575 576
    return new_env;
}

577
#if !defined(CONFIG_USER_ONLY)
J
Juan Quintela 已提交
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t end,
                                      uintptr_t length)
{
    uintptr_t start1;

    /* we modify the TLB cache so that the dirty bit will be set again
       when accessing the range */
    start1 = (uintptr_t)qemu_safe_ram_ptr(start);
    /* Check that we don't span multiple blocks - this breaks the
       address comparisons below.  */
    if ((uintptr_t)qemu_safe_ram_ptr(end - 1) - start1
            != (end - 1) - start) {
        abort();
    }
    cpu_tlb_reset_dirty_all(start1, length);

}

P
pbrook 已提交
596
/* Note: start and end must be within the same ram block.  */
A
Anthony Liguori 已提交
597
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
B
bellard 已提交
598
                                     int dirty_flags)
599
{
J
Juan Quintela 已提交
600
    uintptr_t length;
601 602 603 604 605 606 607

    start &= TARGET_PAGE_MASK;
    end = TARGET_PAGE_ALIGN(end);

    length = end - start;
    if (length == 0)
        return;
608
    cpu_physical_memory_mask_dirty_range(start, length, dirty_flags);
B
bellard 已提交
609

J
Juan Quintela 已提交
610 611
    if (tcg_enabled()) {
        tlb_reset_dirty_range_all(start, end, length);
P
pbrook 已提交
612
    }
613 614
}

B
Blue Swirl 已提交
615
static int cpu_physical_memory_set_dirty_tracking(int enable)
A
aliguori 已提交
616
{
M
Michael S. Tsirkin 已提交
617
    int ret = 0;
A
aliguori 已提交
618
    in_migration = enable;
M
Michael S. Tsirkin 已提交
619
    return ret;
A
aliguori 已提交
620 621
}

A
Avi Kivity 已提交
622
hwaddr memory_region_section_get_iotlb(CPUArchState *env,
B
Blue Swirl 已提交
623 624
                                                   MemoryRegionSection *section,
                                                   target_ulong vaddr,
A
Avi Kivity 已提交
625
                                                   hwaddr paddr,
B
Blue Swirl 已提交
626 627 628
                                                   int prot,
                                                   target_ulong *address)
{
A
Avi Kivity 已提交
629
    hwaddr iotlb;
B
Blue Swirl 已提交
630 631
    CPUWatchpoint *wp;

632
    if (memory_region_is_ram(section->mr)) {
B
Blue Swirl 已提交
633 634
        /* Normal RAM.  */
        iotlb = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
635
            + memory_region_section_addr(section, paddr);
B
Blue Swirl 已提交
636 637 638 639 640 641 642
        if (!section->readonly) {
            iotlb |= phys_section_notdirty;
        } else {
            iotlb |= phys_section_rom;
        }
    } else {
        iotlb = section - phys_sections;
643
        iotlb += memory_region_section_addr(section, paddr);
B
Blue Swirl 已提交
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
    }

    /* Make accesses to pages with watchpoints go via the
       watchpoint trap routines.  */
    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
        if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
            /* Avoid trapping reads of pages with a write breakpoint. */
            if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) {
                iotlb = phys_section_watch + paddr;
                *address |= TLB_MMIO;
                break;
            }
        }
    }

    return iotlb;
}
661 662
#endif /* defined(CONFIG_USER_ONLY) */

663
#if !defined(CONFIG_USER_ONLY)
664

P
Paul Brook 已提交
665 666
#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
typedef struct subpage_t {
667
    MemoryRegion iomem;
A
Avi Kivity 已提交
668
    hwaddr base;
669
    uint16_t sub_section[TARGET_PAGE_SIZE];
P
Paul Brook 已提交
670 671
} subpage_t;

A
Anthony Liguori 已提交
672
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
673
                             uint16_t section);
A
Avi Kivity 已提交
674
static subpage_t *subpage_init(hwaddr base);
675
static void destroy_page_desc(uint16_t section_index)
676
{
677 678
    MemoryRegionSection *section = &phys_sections[section_index];
    MemoryRegion *mr = section->mr;
679 680 681 682 683 684 685 686

    if (mr->subpage) {
        subpage_t *subpage = container_of(mr, subpage_t, iomem);
        memory_region_destroy(&subpage->iomem);
        g_free(subpage);
    }
}

687
static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level)
688 689
{
    unsigned i;
690
    PhysPageEntry *p;
691

692
    if (lp->ptr == PHYS_MAP_NODE_NIL) {
693 694 695
        return;
    }

696
    p = phys_map_nodes[lp->ptr];
697
    for (i = 0; i < L2_SIZE; ++i) {
698
        if (!p[i].is_leaf) {
699
            destroy_l2_mapping(&p[i], level - 1);
700
        } else {
701
            destroy_page_desc(p[i].ptr);
702 703
        }
    }
704
    lp->is_leaf = 0;
705
    lp->ptr = PHYS_MAP_NODE_NIL;
706 707
}

A
Avi Kivity 已提交
708
static void destroy_all_mappings(AddressSpaceDispatch *d)
709
{
A
Avi Kivity 已提交
710
    destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1);
711
    phys_map_nodes_reset();
712 713
}

714 715
static uint16_t phys_section_add(MemoryRegionSection *section)
{
716 717 718 719 720 721
    /* The physical section number is ORed with a page-aligned
     * pointer to produce the iotlb entries.  Thus it should
     * never overflow into the page-aligned value.
     */
    assert(phys_sections_nb < TARGET_PAGE_SIZE);

722 723 724 725 726 727 728 729 730 731 732 733 734 735
    if (phys_sections_nb == phys_sections_nb_alloc) {
        phys_sections_nb_alloc = MAX(phys_sections_nb_alloc * 2, 16);
        phys_sections = g_renew(MemoryRegionSection, phys_sections,
                                phys_sections_nb_alloc);
    }
    phys_sections[phys_sections_nb] = *section;
    return phys_sections_nb++;
}

static void phys_sections_clear(void)
{
    phys_sections_nb = 0;
}

A
Avi Kivity 已提交
736
static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *section)
737 738
{
    subpage_t *subpage;
A
Avi Kivity 已提交
739
    hwaddr base = section->offset_within_address_space
740
        & TARGET_PAGE_MASK;
A
Avi Kivity 已提交
741
    MemoryRegionSection *existing = phys_page_find(d, base >> TARGET_PAGE_BITS);
742 743 744 745
    MemoryRegionSection subsection = {
        .offset_within_address_space = base,
        .size = TARGET_PAGE_SIZE,
    };
A
Avi Kivity 已提交
746
    hwaddr start, end;
747

748
    assert(existing->mr->subpage || existing->mr == &io_mem_unassigned);
749

750
    if (!(existing->mr->subpage)) {
751 752
        subpage = subpage_init(base);
        subsection.mr = &subpage->iomem;
A
Avi Kivity 已提交
753
        phys_page_set(d, base >> TARGET_PAGE_BITS, 1,
754
                      phys_section_add(&subsection));
755
    } else {
756
        subpage = container_of(existing->mr, subpage_t, iomem);
757 758
    }
    start = section->offset_within_address_space & ~TARGET_PAGE_MASK;
759
    end = start + section->size - 1;
760 761 762 763
    subpage_register(subpage, start, end, phys_section_add(section));
}


A
Avi Kivity 已提交
764
static void register_multipage(AddressSpaceDispatch *d, MemoryRegionSection *section)
765
{
A
Avi Kivity 已提交
766
    hwaddr start_addr = section->offset_within_address_space;
767
    ram_addr_t size = section->size;
A
Avi Kivity 已提交
768
    hwaddr addr;
769
    uint16_t section_index = phys_section_add(section);
770

771
    assert(size);
M
Michael S. Tsirkin 已提交
772

773
    addr = start_addr;
A
Avi Kivity 已提交
774
    phys_page_set(d, addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS,
775
                  section_index);
776 777
}

A
Avi Kivity 已提交
778
static void mem_add(MemoryListener *listener, MemoryRegionSection *section)
779
{
A
Avi Kivity 已提交
780
    AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener);
781 782 783 784 785 786 787
    MemoryRegionSection now = *section, remain = *section;

    if ((now.offset_within_address_space & ~TARGET_PAGE_MASK)
        || (now.size < TARGET_PAGE_SIZE)) {
        now.size = MIN(TARGET_PAGE_ALIGN(now.offset_within_address_space)
                       - now.offset_within_address_space,
                       now.size);
A
Avi Kivity 已提交
788
        register_subpage(d, &now);
789 790 791 792
        remain.size -= now.size;
        remain.offset_within_address_space += now.size;
        remain.offset_within_region += now.size;
    }
793 794 795 796
    while (remain.size >= TARGET_PAGE_SIZE) {
        now = remain;
        if (remain.offset_within_region & ~TARGET_PAGE_MASK) {
            now.size = TARGET_PAGE_SIZE;
A
Avi Kivity 已提交
797
            register_subpage(d, &now);
798 799
        } else {
            now.size &= TARGET_PAGE_MASK;
A
Avi Kivity 已提交
800
            register_multipage(d, &now);
801
        }
802 803 804 805 806 807
        remain.size -= now.size;
        remain.offset_within_address_space += now.size;
        remain.offset_within_region += now.size;
    }
    now = remain;
    if (now.size) {
A
Avi Kivity 已提交
808
        register_subpage(d, &now);
809 810 811
    }
}

812 813 814 815 816 817
void qemu_flush_coalesced_mmio_buffer(void)
{
    if (kvm_enabled())
        kvm_flush_coalesced_mmio_buffer();
}

818 819 820 821 822 823 824 825 826 827
void qemu_mutex_lock_ramlist(void)
{
    qemu_mutex_lock(&ram_list.mutex);
}

void qemu_mutex_unlock_ramlist(void)
{
    qemu_mutex_unlock(&ram_list.mutex);
}

828 829 830 831 832 833 834 835 836 837 838 839
#if defined(__linux__) && !defined(TARGET_S390X)

#include <sys/vfs.h>

#define HUGETLBFS_MAGIC       0x958458f6

static long gethugepagesize(const char *path)
{
    struct statfs fs;
    int ret;

    do {
Y
Yoshiaki Tamura 已提交
840
        ret = statfs(path, &fs);
841 842 843
    } while (ret != 0 && errno == EINTR);

    if (ret != 0) {
Y
Yoshiaki Tamura 已提交
844 845
        perror(path);
        return 0;
846 847 848
    }

    if (fs.f_type != HUGETLBFS_MAGIC)
Y
Yoshiaki Tamura 已提交
849
        fprintf(stderr, "Warning: path not on HugeTLBFS: %s\n", path);
850 851 852 853

    return fs.f_bsize;
}

A
Alex Williamson 已提交
854 855 856
static void *file_ram_alloc(RAMBlock *block,
                            ram_addr_t memory,
                            const char *path)
857 858
{
    char *filename;
859 860
    char *sanitized_name;
    char *c;
861 862 863 864 865 866 867 868 869
    void *area;
    int fd;
#ifdef MAP_POPULATE
    int flags;
#endif
    unsigned long hpagesize;

    hpagesize = gethugepagesize(path);
    if (!hpagesize) {
Y
Yoshiaki Tamura 已提交
870
        return NULL;
871 872 873 874 875 876 877 878 879 880 881
    }

    if (memory < hpagesize) {
        return NULL;
    }

    if (kvm_enabled() && !kvm_has_sync_mmu()) {
        fprintf(stderr, "host lacks kvm mmu notifiers, -mem-path unsupported\n");
        return NULL;
    }

882 883 884 885 886 887 888 889 890 891
    /* Make name safe to use with mkstemp by replacing '/' with '_'. */
    sanitized_name = g_strdup(block->mr->name);
    for (c = sanitized_name; *c != '\0'; c++) {
        if (*c == '/')
            *c = '_';
    }

    filename = g_strdup_printf("%s/qemu_back_mem.%s.XXXXXX", path,
                               sanitized_name);
    g_free(sanitized_name);
892 893 894

    fd = mkstemp(filename);
    if (fd < 0) {
Y
Yoshiaki Tamura 已提交
895
        perror("unable to create backing store for hugepages");
896
        g_free(filename);
Y
Yoshiaki Tamura 已提交
897
        return NULL;
898 899
    }
    unlink(filename);
900
    g_free(filename);
901 902 903 904 905 906 907 908 909 910

    memory = (memory+hpagesize-1) & ~(hpagesize-1);

    /*
     * ftruncate is not supported by hugetlbfs in older
     * hosts, so don't bother bailing out on errors.
     * If anything goes wrong with it under other filesystems,
     * mmap will fail.
     */
    if (ftruncate(fd, memory))
Y
Yoshiaki Tamura 已提交
911
        perror("ftruncate");
912 913 914 915 916 917 918 919 920 921 922 923

#ifdef MAP_POPULATE
    /* NB: MAP_POPULATE won't exhaustively alloc all phys pages in the case
     * MAP_PRIVATE is requested.  For mem_prealloc we mmap as MAP_SHARED
     * to sidestep this quirk.
     */
    flags = mem_prealloc ? MAP_POPULATE | MAP_SHARED : MAP_PRIVATE;
    area = mmap(0, memory, PROT_READ | PROT_WRITE, flags, fd, 0);
#else
    area = mmap(0, memory, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
#endif
    if (area == MAP_FAILED) {
Y
Yoshiaki Tamura 已提交
924 925 926
        perror("file_ram_alloc: can't mmap RAM pages");
        close(fd);
        return (NULL);
927
    }
A
Alex Williamson 已提交
928
    block->fd = fd;
929 930 931 932
    return area;
}
#endif

933
static ram_addr_t find_ram_offset(ram_addr_t size)
A
Alex Williamson 已提交
934 935
{
    RAMBlock *block, *next_block;
A
Alex Williamson 已提交
936
    ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX;
A
Alex Williamson 已提交
937

938 939
    assert(size != 0); /* it would hand out same offset multiple times */

P
Paolo Bonzini 已提交
940
    if (QTAILQ_EMPTY(&ram_list.blocks))
A
Alex Williamson 已提交
941 942
        return 0;

P
Paolo Bonzini 已提交
943
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
944
        ram_addr_t end, next = RAM_ADDR_MAX;
A
Alex Williamson 已提交
945 946 947

        end = block->offset + block->length;

P
Paolo Bonzini 已提交
948
        QTAILQ_FOREACH(next_block, &ram_list.blocks, next) {
A
Alex Williamson 已提交
949 950 951 952 953
            if (next_block->offset >= end) {
                next = MIN(next, next_block->offset);
            }
        }
        if (next - end >= size && next - end < mingap) {
A
Alex Williamson 已提交
954
            offset = end;
A
Alex Williamson 已提交
955 956 957
            mingap = next - end;
        }
    }
A
Alex Williamson 已提交
958 959 960 961 962 963 964

    if (offset == RAM_ADDR_MAX) {
        fprintf(stderr, "Failed to find gap of requested size: %" PRIu64 "\n",
                (uint64_t)size);
        abort();
    }

A
Alex Williamson 已提交
965 966 967
    return offset;
}

J
Juan Quintela 已提交
968
ram_addr_t last_ram_offset(void)
969 970 971 972
{
    RAMBlock *block;
    ram_addr_t last = 0;

P
Paolo Bonzini 已提交
973
    QTAILQ_FOREACH(block, &ram_list.blocks, next)
974 975 976 977 978
        last = MAX(last, block->offset + block->length);

    return last;
}

979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996
static void qemu_ram_setup_dump(void *addr, ram_addr_t size)
{
    int ret;
    QemuOpts *machine_opts;

    /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */
    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
    if (machine_opts &&
        !qemu_opt_get_bool(machine_opts, "dump-guest-core", true)) {
        ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP);
        if (ret) {
            perror("qemu_madvise");
            fprintf(stderr, "madvise doesn't support MADV_DONTDUMP, "
                            "but dump_guest_core=off specified\n");
        }
    }
}

997
void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
998 999 1000
{
    RAMBlock *new_block, *block;

1001
    new_block = NULL;
P
Paolo Bonzini 已提交
1002
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1003 1004 1005 1006 1007 1008 1009
        if (block->offset == addr) {
            new_block = block;
            break;
        }
    }
    assert(new_block);
    assert(!new_block->idstr[0]);
1010

1011 1012
    if (dev) {
        char *id = qdev_get_dev_path(dev);
1013 1014
        if (id) {
            snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
1015
            g_free(id);
1016 1017 1018 1019
        }
    }
    pstrcat(new_block->idstr, sizeof(new_block->idstr), name);

1020 1021
    /* This assumes the iothread lock is taken here too.  */
    qemu_mutex_lock_ramlist();
P
Paolo Bonzini 已提交
1022
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1023
        if (block != new_block && !strcmp(block->idstr, new_block->idstr)) {
1024 1025 1026 1027 1028
            fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
                    new_block->idstr);
            abort();
        }
    }
1029
    qemu_mutex_unlock_ramlist();
1030 1031
}

1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
static int memory_try_enable_merging(void *addr, size_t len)
{
    QemuOpts *opts;

    opts = qemu_opts_find(qemu_find_opts("machine"), 0);
    if (opts && !qemu_opt_get_bool(opts, "mem-merge", true)) {
        /* disabled by the user */
        return 0;
    }

    return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE);
}

1045 1046 1047
ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
                                   MemoryRegion *mr)
{
1048
    RAMBlock *block, *new_block;
1049 1050 1051

    size = TARGET_PAGE_ALIGN(size);
    new_block = g_malloc0(sizeof(*new_block));
1052

1053 1054
    /* This assumes the iothread lock is taken here too.  */
    qemu_mutex_lock_ramlist();
A
Avi Kivity 已提交
1055
    new_block->mr = mr;
J
Jun Nakajima 已提交
1056
    new_block->offset = find_ram_offset(size);
1057 1058
    if (host) {
        new_block->host = host;
H
Huang Ying 已提交
1059
        new_block->flags |= RAM_PREALLOC_MASK;
1060 1061
    } else {
        if (mem_path) {
1062
#if defined (__linux__) && !defined(TARGET_S390X)
1063 1064
            new_block->host = file_ram_alloc(new_block, size, mem_path);
            if (!new_block->host) {
1065
                new_block->host = qemu_anon_ram_alloc(size);
1066
                memory_try_enable_merging(new_block->host, size);
1067
            }
1068
#else
1069 1070
            fprintf(stderr, "-mem-path option unsupported\n");
            exit(1);
1071
#endif
1072
        } else {
1073
            if (xen_enabled()) {
1074
                xen_ram_alloc(new_block->offset, size, mr);
1075 1076
            } else if (kvm_enabled()) {
                /* some s390/kvm configurations have special constraints */
1077
                new_block->host = kvm_ram_alloc(size);
J
Jun Nakajima 已提交
1078
            } else {
1079
                new_block->host = qemu_anon_ram_alloc(size);
J
Jun Nakajima 已提交
1080
            }
1081
            memory_try_enable_merging(new_block->host, size);
1082
        }
1083
    }
P
pbrook 已提交
1084 1085
    new_block->length = size;

1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
    /* Keep the list sorted from biggest to smallest block.  */
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
        if (block->length < new_block->length) {
            break;
        }
    }
    if (block) {
        QTAILQ_INSERT_BEFORE(block, new_block, next);
    } else {
        QTAILQ_INSERT_TAIL(&ram_list.blocks, new_block, next);
    }
1097
    ram_list.mru_block = NULL;
P
pbrook 已提交
1098

U
Umesh Deshpande 已提交
1099
    ram_list.version++;
1100
    qemu_mutex_unlock_ramlist();
U
Umesh Deshpande 已提交
1101

1102
    ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
A
Alex Williamson 已提交
1103
                                       last_ram_offset() >> TARGET_PAGE_BITS);
1104 1105
    memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
           0, size >> TARGET_PAGE_BITS);
J
Juan Quintela 已提交
1106
    cpu_physical_memory_set_dirty_range(new_block->offset, size, 0xff);
P
pbrook 已提交
1107

1108
    qemu_ram_setup_dump(new_block->host, size);
1109
    qemu_madvise(new_block->host, size, QEMU_MADV_HUGEPAGE);
1110

1111 1112 1113
    if (kvm_enabled())
        kvm_setup_guest_memory(new_block->host, size);

P
pbrook 已提交
1114 1115
    return new_block->offset;
}
B
bellard 已提交
1116

1117
ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr)
1118
{
1119
    return qemu_ram_alloc_from_ptr(size, NULL, mr);
1120 1121
}

1122 1123 1124 1125
void qemu_ram_free_from_ptr(ram_addr_t addr)
{
    RAMBlock *block;

1126 1127
    /* This assumes the iothread lock is taken here too.  */
    qemu_mutex_lock_ramlist();
P
Paolo Bonzini 已提交
1128
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1129
        if (addr == block->offset) {
P
Paolo Bonzini 已提交
1130
            QTAILQ_REMOVE(&ram_list.blocks, block, next);
1131
            ram_list.mru_block = NULL;
U
Umesh Deshpande 已提交
1132
            ram_list.version++;
1133
            g_free(block);
1134
            break;
1135 1136
        }
    }
1137
    qemu_mutex_unlock_ramlist();
1138 1139
}

A
Anthony Liguori 已提交
1140
void qemu_ram_free(ram_addr_t addr)
B
bellard 已提交
1141
{
A
Alex Williamson 已提交
1142 1143
    RAMBlock *block;

1144 1145
    /* This assumes the iothread lock is taken here too.  */
    qemu_mutex_lock_ramlist();
P
Paolo Bonzini 已提交
1146
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
A
Alex Williamson 已提交
1147
        if (addr == block->offset) {
P
Paolo Bonzini 已提交
1148
            QTAILQ_REMOVE(&ram_list.blocks, block, next);
1149
            ram_list.mru_block = NULL;
U
Umesh Deshpande 已提交
1150
            ram_list.version++;
H
Huang Ying 已提交
1151 1152 1153
            if (block->flags & RAM_PREALLOC_MASK) {
                ;
            } else if (mem_path) {
A
Alex Williamson 已提交
1154 1155 1156 1157 1158
#if defined (__linux__) && !defined(TARGET_S390X)
                if (block->fd) {
                    munmap(block->host, block->length);
                    close(block->fd);
                } else {
1159
                    qemu_anon_ram_free(block->host, block->length);
A
Alex Williamson 已提交
1160
                }
1161 1162
#else
                abort();
A
Alex Williamson 已提交
1163 1164
#endif
            } else {
1165
                if (xen_enabled()) {
J
Jan Kiszka 已提交
1166
                    xen_invalidate_map_cache_entry(block->host);
J
Jun Nakajima 已提交
1167
                } else {
1168
                    qemu_anon_ram_free(block->host, block->length);
J
Jun Nakajima 已提交
1169
                }
A
Alex Williamson 已提交
1170
            }
1171
            g_free(block);
1172
            break;
A
Alex Williamson 已提交
1173 1174
        }
    }
1175
    qemu_mutex_unlock_ramlist();
A
Alex Williamson 已提交
1176

B
bellard 已提交
1177 1178
}

H
Huang Ying 已提交
1179 1180 1181 1182 1183 1184 1185 1186
#ifndef _WIN32
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
{
    RAMBlock *block;
    ram_addr_t offset;
    int flags;
    void *area, *vaddr;

P
Paolo Bonzini 已提交
1187
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
H
Huang Ying 已提交
1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211
        offset = addr - block->offset;
        if (offset < block->length) {
            vaddr = block->host + offset;
            if (block->flags & RAM_PREALLOC_MASK) {
                ;
            } else {
                flags = MAP_FIXED;
                munmap(vaddr, length);
                if (mem_path) {
#if defined(__linux__) && !defined(TARGET_S390X)
                    if (block->fd) {
#ifdef MAP_POPULATE
                        flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
                            MAP_PRIVATE;
#else
                        flags |= MAP_PRIVATE;
#endif
                        area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
                                    flags, block->fd, offset);
                    } else {
                        flags |= MAP_PRIVATE | MAP_ANONYMOUS;
                        area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
                                    flags, -1, 0);
                    }
1212 1213
#else
                    abort();
H
Huang Ying 已提交
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
#endif
                } else {
#if defined(TARGET_S390X) && defined(CONFIG_KVM)
                    flags |= MAP_SHARED | MAP_ANONYMOUS;
                    area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE,
                                flags, -1, 0);
#else
                    flags |= MAP_PRIVATE | MAP_ANONYMOUS;
                    area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
                                flags, -1, 0);
#endif
                }
                if (area != vaddr) {
1227 1228
                    fprintf(stderr, "Could not remap addr: "
                            RAM_ADDR_FMT "@" RAM_ADDR_FMT "\n",
H
Huang Ying 已提交
1229 1230 1231
                            length, addr);
                    exit(1);
                }
1232
                memory_try_enable_merging(vaddr, length);
1233
                qemu_ram_setup_dump(vaddr, length);
H
Huang Ying 已提交
1234 1235 1236 1237 1238 1239 1240
            }
            return;
        }
    }
}
#endif /* !_WIN32 */

1241
/* Return a host pointer to ram allocated with qemu_ram_alloc.
P
pbrook 已提交
1242 1243 1244 1245 1246 1247 1248
   With the exception of the softmmu code in this file, this should
   only be used for local memory (e.g. video ram) that the device owns,
   and knows it isn't going to access beyond the end of the block.

   It should not be used for general purpose DMA.
   Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
 */
A
Anthony Liguori 已提交
1249
void *qemu_get_ram_ptr(ram_addr_t addr)
1250
{
P
pbrook 已提交
1251 1252
    RAMBlock *block;

1253
    /* The list is protected by the iothread lock here.  */
1254 1255 1256 1257
    block = ram_list.mru_block;
    if (block && addr - block->offset < block->length) {
        goto found;
    }
P
Paolo Bonzini 已提交
1258
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
A
Alex Williamson 已提交
1259
        if (addr - block->offset < block->length) {
1260
            goto found;
A
Alex Williamson 已提交
1261
        }
P
pbrook 已提交
1262
    }
A
Alex Williamson 已提交
1263 1264 1265 1266

    fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
    abort();

1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281
found:
    ram_list.mru_block = block;
    if (xen_enabled()) {
        /* We need to check if the requested address is in the RAM
         * because we don't want to map the entire memory in QEMU.
         * In that case just map until the end of the page.
         */
        if (block->offset == 0) {
            return xen_map_cache(addr, 0, 0);
        } else if (block->host == NULL) {
            block->host =
                xen_map_cache(block->offset, block->length, 1);
        }
    }
    return block->host + (addr - block->offset);
1282 1283
}

1284 1285 1286 1287
/* Return a host pointer to ram allocated with qemu_ram_alloc.  Same as
 * qemu_get_ram_ptr but do not touch ram_list.mru_block.
 *
 * ??? Is this still necessary?
1288
 */
B
Blue Swirl 已提交
1289
static void *qemu_safe_ram_ptr(ram_addr_t addr)
1290 1291 1292
{
    RAMBlock *block;

1293
    /* The list is protected by the iothread lock here.  */
P
Paolo Bonzini 已提交
1294
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1295
        if (addr - block->offset < block->length) {
1296
            if (xen_enabled()) {
J
Jun Nakajima 已提交
1297 1298
                /* We need to check if the requested address is in the RAM
                 * because we don't want to map the entire memory in QEMU.
1299
                 * In that case just map until the end of the page.
J
Jun Nakajima 已提交
1300 1301
                 */
                if (block->offset == 0) {
J
Jan Kiszka 已提交
1302
                    return xen_map_cache(addr, 0, 0);
J
Jun Nakajima 已提交
1303
                } else if (block->host == NULL) {
J
Jan Kiszka 已提交
1304 1305
                    block->host =
                        xen_map_cache(block->offset, block->length, 1);
J
Jun Nakajima 已提交
1306 1307
                }
            }
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317
            return block->host + (addr - block->offset);
        }
    }

    fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
    abort();

    return NULL;
}

1318 1319
/* Return a host pointer to guest's ram. Similar to qemu_get_ram_ptr
 * but takes a size argument */
B
Blue Swirl 已提交
1320
static void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size)
1321
{
1322 1323 1324
    if (*size == 0) {
        return NULL;
    }
1325
    if (xen_enabled()) {
J
Jan Kiszka 已提交
1326
        return xen_map_cache(addr, *size, 1);
1327
    } else {
1328 1329
        RAMBlock *block;

P
Paolo Bonzini 已提交
1330
        QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342
            if (addr - block->offset < block->length) {
                if (addr - block->offset + *size > block->length)
                    *size = block->length - addr + block->offset;
                return block->host + (addr - block->offset);
            }
        }

        fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
        abort();
    }
}

M
Marcelo Tosatti 已提交
1343
int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
P
pbrook 已提交
1344
{
P
pbrook 已提交
1345 1346 1347
    RAMBlock *block;
    uint8_t *host = ptr;

1348
    if (xen_enabled()) {
J
Jan Kiszka 已提交
1349
        *ram_addr = xen_ram_addr_from_mapcache(ptr);
1350 1351 1352
        return 0;
    }

P
Paolo Bonzini 已提交
1353
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
J
Jun Nakajima 已提交
1354 1355 1356 1357
        /* This case append when the block is not mapped. */
        if (block->host == NULL) {
            continue;
        }
A
Alex Williamson 已提交
1358
        if (host - block->host < block->length) {
M
Marcelo Tosatti 已提交
1359 1360
            *ram_addr = block->offset + (host - block->host);
            return 0;
A
Alex Williamson 已提交
1361
        }
P
pbrook 已提交
1362
    }
J
Jun Nakajima 已提交
1363

M
Marcelo Tosatti 已提交
1364 1365
    return -1;
}
A
Alex Williamson 已提交
1366

M
Marcelo Tosatti 已提交
1367 1368 1369 1370 1371
/* Some of the softmmu routines need to translate from a host pointer
   (typically a TLB entry) back to a ram offset.  */
ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
{
    ram_addr_t ram_addr;
A
Alex Williamson 已提交
1372

M
Marcelo Tosatti 已提交
1373 1374 1375 1376 1377
    if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
        fprintf(stderr, "Bad ram pointer %p\n", ptr);
        abort();
    }
    return ram_addr;
P
pbrook 已提交
1378 1379
}

A
Avi Kivity 已提交
1380
static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
1381
                                    unsigned size)
1382 1383 1384 1385
{
#ifdef DEBUG_UNASSIGNED
    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
1386
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
1387
    cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
1388 1389 1390 1391
#endif
    return 0;
}

A
Avi Kivity 已提交
1392
static void unassigned_mem_write(void *opaque, hwaddr addr,
1393
                                 uint64_t val, unsigned size)
1394 1395
{
#ifdef DEBUG_UNASSIGNED
1396
    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val);
1397
#endif
1398
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
1399
    cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
P
pbrook 已提交
1400
#endif
1401 1402
}

1403 1404 1405 1406 1407
static const MemoryRegionOps unassigned_mem_ops = {
    .read = unassigned_mem_read,
    .write = unassigned_mem_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
};
1408

A
Avi Kivity 已提交
1409
static uint64_t error_mem_read(void *opaque, hwaddr addr,
1410
                               unsigned size)
1411
{
1412
    abort();
1413 1414
}

A
Avi Kivity 已提交
1415
static void error_mem_write(void *opaque, hwaddr addr,
1416
                            uint64_t value, unsigned size)
1417
{
1418
    abort();
1419 1420
}

1421 1422 1423 1424
static const MemoryRegionOps error_mem_ops = {
    .read = error_mem_read,
    .write = error_mem_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
1425 1426
};

1427 1428 1429 1430
static const MemoryRegionOps rom_mem_ops = {
    .read = error_mem_read,
    .write = unassigned_mem_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
1431 1432
};

A
Avi Kivity 已提交
1433
static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
1434
                               uint64_t val, unsigned size)
1435
{
1436
    int dirty_flags;
1437
    dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
1438
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
1439
#if !defined(CONFIG_USER_ONLY)
1440
        tb_invalidate_phys_page_fast(ram_addr, size);
1441
        dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
1442
#endif
1443
    }
1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455
    switch (size) {
    case 1:
        stb_p(qemu_get_ram_ptr(ram_addr), val);
        break;
    case 2:
        stw_p(qemu_get_ram_ptr(ram_addr), val);
        break;
    case 4:
        stl_p(qemu_get_ram_ptr(ram_addr), val);
        break;
    default:
        abort();
1456
    }
B
bellard 已提交
1457
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
1458
    cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
B
bellard 已提交
1459 1460 1461
    /* we remove the notdirty callback only if the code has been
       flushed */
    if (dirty_flags == 0xff)
P
pbrook 已提交
1462
        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
1463 1464
}

1465 1466 1467 1468
static const MemoryRegionOps notdirty_mem_ops = {
    .read = error_mem_read,
    .write = notdirty_mem_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
1469 1470
};

P
pbrook 已提交
1471
/* Generate a debug exception if a watchpoint has been hit.  */
1472
static void check_watchpoint(int offset, int len_mask, int flags)
P
pbrook 已提交
1473
{
1474
    CPUArchState *env = cpu_single_env;
1475
    target_ulong pc, cs_base;
P
pbrook 已提交
1476
    target_ulong vaddr;
1477
    CPUWatchpoint *wp;
1478
    int cpu_flags;
P
pbrook 已提交
1479

1480 1481 1482 1483
    if (env->watchpoint_hit) {
        /* We re-entered the check after replacing the TB. Now raise
         * the debug interrupt so that is will trigger after the
         * current instruction. */
1484
        cpu_interrupt(ENV_GET_CPU(env), CPU_INTERRUPT_DEBUG);
1485 1486
        return;
    }
P
pbrook 已提交
1487
    vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
B
Blue Swirl 已提交
1488
    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
1489 1490
        if ((vaddr == (wp->vaddr & len_mask) ||
             (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
1491 1492 1493
            wp->flags |= BP_WATCHPOINT_HIT;
            if (!env->watchpoint_hit) {
                env->watchpoint_hit = wp;
B
Blue Swirl 已提交
1494
                tb_check_watchpoint(env);
1495 1496
                if (wp->flags & BP_STOP_BEFORE_ACCESS) {
                    env->exception_index = EXCP_DEBUG;
1497
                    cpu_loop_exit(env);
1498 1499 1500
                } else {
                    cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
                    tb_gen_code(env, pc, cs_base, cpu_flags, 1);
1501
                    cpu_resume_from_signal(env, NULL);
1502
                }
1503
            }
1504 1505
        } else {
            wp->flags &= ~BP_WATCHPOINT_HIT;
P
pbrook 已提交
1506 1507 1508 1509
        }
    }
}

1510 1511 1512
/* Watchpoint access routines.  Watchpoints are inserted using TLB tricks,
   so these check for a hit then pass through to the normal out-of-line
   phys routines.  */
A
Avi Kivity 已提交
1513
static uint64_t watch_mem_read(void *opaque, hwaddr addr,
1514
                               unsigned size)
1515
{
1516 1517 1518 1519 1520 1521 1522
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_READ);
    switch (size) {
    case 1: return ldub_phys(addr);
    case 2: return lduw_phys(addr);
    case 4: return ldl_phys(addr);
    default: abort();
    }
1523 1524
}

A
Avi Kivity 已提交
1525
static void watch_mem_write(void *opaque, hwaddr addr,
1526
                            uint64_t val, unsigned size)
1527
{
1528 1529
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_WRITE);
    switch (size) {
1530 1531 1532 1533 1534 1535 1536 1537 1538
    case 1:
        stb_phys(addr, val);
        break;
    case 2:
        stw_phys(addr, val);
        break;
    case 4:
        stl_phys(addr, val);
        break;
1539 1540
    default: abort();
    }
1541 1542
}

1543 1544 1545 1546
static const MemoryRegionOps watch_mem_ops = {
    .read = watch_mem_read,
    .write = watch_mem_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
1547 1548
};

A
Avi Kivity 已提交
1549
static uint64_t subpage_read(void *opaque, hwaddr addr,
1550
                             unsigned len)
1551
{
1552
    subpage_t *mmio = opaque;
R
Richard Henderson 已提交
1553
    unsigned int idx = SUBPAGE_IDX(addr);
1554
    MemoryRegionSection *section;
1555 1556 1557 1558 1559
#if defined(DEBUG_SUBPAGE)
    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
           mmio, len, addr, idx);
#endif

1560 1561 1562 1563
    section = &phys_sections[mmio->sub_section[idx]];
    addr += mmio->base;
    addr -= section->offset_within_address_space;
    addr += section->offset_within_region;
1564
    return io_mem_read(section->mr, addr, len);
1565 1566
}

A
Avi Kivity 已提交
1567
static void subpage_write(void *opaque, hwaddr addr,
1568
                          uint64_t value, unsigned len)
1569
{
1570
    subpage_t *mmio = opaque;
R
Richard Henderson 已提交
1571
    unsigned int idx = SUBPAGE_IDX(addr);
1572
    MemoryRegionSection *section;
1573
#if defined(DEBUG_SUBPAGE)
1574 1575
    printf("%s: subpage %p len %d addr " TARGET_FMT_plx
           " idx %d value %"PRIx64"\n",
R
Richard Henderson 已提交
1576
           __func__, mmio, len, addr, idx, value);
1577
#endif
R
Richard Henderson 已提交
1578

1579 1580 1581 1582
    section = &phys_sections[mmio->sub_section[idx]];
    addr += mmio->base;
    addr -= section->offset_within_address_space;
    addr += section->offset_within_region;
1583
    io_mem_write(section->mr, addr, value, len);
1584 1585
}

1586 1587 1588 1589
static const MemoryRegionOps subpage_ops = {
    .read = subpage_read,
    .write = subpage_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
1590 1591
};

A
Avi Kivity 已提交
1592
static uint64_t subpage_ram_read(void *opaque, hwaddr addr,
1593
                                 unsigned size)
1594 1595 1596
{
    ram_addr_t raddr = addr;
    void *ptr = qemu_get_ram_ptr(raddr);
1597 1598 1599 1600 1601 1602
    switch (size) {
    case 1: return ldub_p(ptr);
    case 2: return lduw_p(ptr);
    case 4: return ldl_p(ptr);
    default: abort();
    }
1603 1604
}

A
Avi Kivity 已提交
1605
static void subpage_ram_write(void *opaque, hwaddr addr,
1606
                              uint64_t value, unsigned size)
1607 1608 1609
{
    ram_addr_t raddr = addr;
    void *ptr = qemu_get_ram_ptr(raddr);
1610 1611 1612 1613 1614 1615
    switch (size) {
    case 1: return stb_p(ptr, value);
    case 2: return stw_p(ptr, value);
    case 4: return stl_p(ptr, value);
    default: abort();
    }
1616 1617
}

1618 1619 1620 1621
static const MemoryRegionOps subpage_ram_ops = {
    .read = subpage_ram_read,
    .write = subpage_ram_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
1622 1623
};

A
Anthony Liguori 已提交
1624
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
1625
                             uint16_t section)
1626 1627 1628 1629 1630 1631 1632 1633
{
    int idx, eidx;

    if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
        return -1;
    idx = SUBPAGE_IDX(start);
    eidx = SUBPAGE_IDX(end);
#if defined(DEBUG_SUBPAGE)
1634
    printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
1635 1636
           mmio, start, end, idx, eidx, memory);
#endif
1637 1638 1639 1640
    if (memory_region_is_ram(phys_sections[section].mr)) {
        MemoryRegionSection new_section = phys_sections[section];
        new_section.mr = &io_mem_subpage_ram;
        section = phys_section_add(&new_section);
1641
    }
1642
    for (; idx <= eidx; idx++) {
1643
        mmio->sub_section[idx] = section;
1644 1645 1646 1647 1648
    }

    return 0;
}

A
Avi Kivity 已提交
1649
static subpage_t *subpage_init(hwaddr base)
1650
{
A
Anthony Liguori 已提交
1651
    subpage_t *mmio;
1652

1653
    mmio = g_malloc0(sizeof(subpage_t));
1654 1655

    mmio->base = base;
1656 1657
    memory_region_init_io(&mmio->iomem, &subpage_ops, mmio,
                          "subpage", TARGET_PAGE_SIZE);
A
Avi Kivity 已提交
1658
    mmio->iomem.subpage = true;
1659
#if defined(DEBUG_SUBPAGE)
1660 1661
    printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
           mmio, base, TARGET_PAGE_SIZE, subpage_memory);
1662
#endif
1663
    subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, phys_section_unassigned);
1664 1665 1666 1667

    return mmio;
}

1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679
static uint16_t dummy_section(MemoryRegion *mr)
{
    MemoryRegionSection section = {
        .mr = mr,
        .offset_within_address_space = 0,
        .offset_within_region = 0,
        .size = UINT64_MAX,
    };

    return phys_section_add(&section);
}

A
Avi Kivity 已提交
1680
MemoryRegion *iotlb_to_region(hwaddr index)
1681
{
1682
    return phys_sections[index & ~TARGET_PAGE_MASK].mr;
1683 1684
}

A
Avi Kivity 已提交
1685 1686
static void io_mem_init(void)
{
1687 1688 1689 1690 1691 1692
    memory_region_init_io(&io_mem_ram, &error_mem_ops, NULL, "ram", UINT64_MAX);
    memory_region_init_io(&io_mem_rom, &rom_mem_ops, NULL, "rom", UINT64_MAX);
    memory_region_init_io(&io_mem_unassigned, &unassigned_mem_ops, NULL,
                          "unassigned", UINT64_MAX);
    memory_region_init_io(&io_mem_notdirty, &notdirty_mem_ops, NULL,
                          "notdirty", UINT64_MAX);
1693 1694
    memory_region_init_io(&io_mem_subpage_ram, &subpage_ram_ops, NULL,
                          "subpage-ram", UINT64_MAX);
1695 1696
    memory_region_init_io(&io_mem_watch, &watch_mem_ops, NULL,
                          "watch", UINT64_MAX);
A
Avi Kivity 已提交
1697 1698
}

A
Avi Kivity 已提交
1699 1700 1701 1702 1703 1704 1705 1706
static void mem_begin(MemoryListener *listener)
{
    AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener);

    destroy_all_mappings(d);
    d->phys_map.ptr = PHYS_MAP_NODE_NIL;
}

1707 1708
static void core_begin(MemoryListener *listener)
{
1709 1710
    phys_sections_clear();
    phys_section_unassigned = dummy_section(&io_mem_unassigned);
1711 1712 1713
    phys_section_notdirty = dummy_section(&io_mem_notdirty);
    phys_section_rom = dummy_section(&io_mem_rom);
    phys_section_watch = dummy_section(&io_mem_watch);
1714 1715
}

1716
static void tcg_commit(MemoryListener *listener)
1717
{
1718
    CPUArchState *env;
1719 1720 1721 1722 1723 1724 1725

    /* since each CPU stores ram addresses in its TLB cache, we must
       reset the modified entries */
    /* XXX: slow ! */
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
        tlb_flush(env, 1);
    }
1726 1727
}

1728 1729 1730 1731 1732 1733 1734 1735 1736 1737
static void core_log_global_start(MemoryListener *listener)
{
    cpu_physical_memory_set_dirty_tracking(1);
}

static void core_log_global_stop(MemoryListener *listener)
{
    cpu_physical_memory_set_dirty_tracking(0);
}

1738 1739 1740
static void io_region_add(MemoryListener *listener,
                          MemoryRegionSection *section)
{
A
Avi Kivity 已提交
1741 1742 1743 1744 1745
    MemoryRegionIORange *mrio = g_new(MemoryRegionIORange, 1);

    mrio->mr = section->mr;
    mrio->offset = section->offset_within_region;
    iorange_init(&mrio->iorange, &memory_region_iorange_ops,
1746
                 section->offset_within_address_space, section->size);
A
Avi Kivity 已提交
1747
    ioport_register(&mrio->iorange);
1748 1749 1750 1751 1752 1753 1754 1755
}

static void io_region_del(MemoryListener *listener,
                          MemoryRegionSection *section)
{
    isa_unassign_ioport(section->offset_within_address_space, section->size);
}

1756
static MemoryListener core_memory_listener = {
1757
    .begin = core_begin,
1758 1759
    .log_global_start = core_log_global_start,
    .log_global_stop = core_log_global_stop,
A
Avi Kivity 已提交
1760
    .priority = 1,
1761 1762
};

1763 1764 1765 1766 1767 1768
static MemoryListener io_memory_listener = {
    .region_add = io_region_add,
    .region_del = io_region_del,
    .priority = 0,
};

1769 1770 1771 1772
static MemoryListener tcg_memory_listener = {
    .commit = tcg_commit,
};

A
Avi Kivity 已提交
1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787
void address_space_init_dispatch(AddressSpace *as)
{
    AddressSpaceDispatch *d = g_new(AddressSpaceDispatch, 1);

    d->phys_map  = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 };
    d->listener = (MemoryListener) {
        .begin = mem_begin,
        .region_add = mem_add,
        .region_nop = mem_add,
        .priority = 0,
    };
    as->dispatch = d;
    memory_listener_register(&d->listener, as);
}

A
Avi Kivity 已提交
1788 1789 1790 1791 1792 1793 1794 1795 1796 1797
void address_space_destroy_dispatch(AddressSpace *as)
{
    AddressSpaceDispatch *d = as->dispatch;

    memory_listener_unregister(&d->listener);
    destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1);
    g_free(d);
    as->dispatch = NULL;
}

A
Avi Kivity 已提交
1798 1799
static void memory_map_init(void)
{
1800
    system_memory = g_malloc(sizeof(*system_memory));
A
Avi Kivity 已提交
1801
    memory_region_init(system_memory, "system", INT64_MAX);
1802 1803
    address_space_init(&address_space_memory, system_memory);
    address_space_memory.name = "memory";
1804

1805
    system_io = g_malloc(sizeof(*system_io));
1806
    memory_region_init(system_io, "io", 65536);
1807 1808
    address_space_init(&address_space_io, system_io);
    address_space_io.name = "I/O";
1809

1810 1811 1812
    memory_listener_register(&core_memory_listener, &address_space_memory);
    memory_listener_register(&io_memory_listener, &address_space_io);
    memory_listener_register(&tcg_memory_listener, &address_space_memory);
1813 1814 1815

    dma_context_init(&dma_context_memory, &address_space_memory,
                     NULL, NULL, NULL);
A
Avi Kivity 已提交
1816 1817 1818 1819 1820 1821 1822
}

MemoryRegion *get_system_memory(void)
{
    return system_memory;
}

1823 1824 1825 1826 1827
MemoryRegion *get_system_io(void)
{
    return system_io;
}

1828 1829
#endif /* !defined(CONFIG_USER_ONLY) */

B
bellard 已提交
1830 1831
/* physical memory access (slow version, mainly for debug) */
#if defined(CONFIG_USER_ONLY)
1832
int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
P
Paul Brook 已提交
1833
                        uint8_t *buf, int len, int is_write)
B
bellard 已提交
1834 1835 1836
{
    int l, flags;
    target_ulong page;
1837
    void * p;
B
bellard 已提交
1838 1839 1840 1841 1842 1843 1844 1845

    while (len > 0) {
        page = addr & TARGET_PAGE_MASK;
        l = (page + TARGET_PAGE_SIZE) - addr;
        if (l > len)
            l = len;
        flags = page_get_flags(page);
        if (!(flags & PAGE_VALID))
P
Paul Brook 已提交
1846
            return -1;
B
bellard 已提交
1847 1848
        if (is_write) {
            if (!(flags & PAGE_WRITE))
P
Paul Brook 已提交
1849
                return -1;
1850
            /* XXX: this code should not depend on lock_user */
A
aurel32 已提交
1851
            if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
P
Paul Brook 已提交
1852
                return -1;
A
aurel32 已提交
1853 1854
            memcpy(p, buf, l);
            unlock_user(p, addr, l);
B
bellard 已提交
1855 1856
        } else {
            if (!(flags & PAGE_READ))
P
Paul Brook 已提交
1857
                return -1;
1858
            /* XXX: this code should not depend on lock_user */
A
aurel32 已提交
1859
            if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
P
Paul Brook 已提交
1860
                return -1;
A
aurel32 已提交
1861
            memcpy(buf, p, l);
A
aurel32 已提交
1862
            unlock_user(p, addr, 0);
B
bellard 已提交
1863 1864 1865 1866 1867
        }
        len -= l;
        buf += l;
        addr += l;
    }
P
Paul Brook 已提交
1868
    return 0;
B
bellard 已提交
1869
}
B
bellard 已提交
1870

B
bellard 已提交
1871
#else
1872

A
Avi Kivity 已提交
1873 1874
static void invalidate_and_set_dirty(hwaddr addr,
                                     hwaddr length)
1875 1876 1877 1878 1879 1880 1881
{
    if (!cpu_physical_memory_is_dirty(addr)) {
        /* invalidate code */
        tb_invalidate_phys_page_range(addr, addr + length, 0);
        /* set dirty bit */
        cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG));
    }
1882
    xen_modified_memory(addr, length);
1883 1884
}

A
Avi Kivity 已提交
1885
void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
A
Avi Kivity 已提交
1886
                      int len, bool is_write)
B
bellard 已提交
1887
{
A
Avi Kivity 已提交
1888
    AddressSpaceDispatch *d = as->dispatch;
1889
    int l;
B
bellard 已提交
1890 1891
    uint8_t *ptr;
    uint32_t val;
A
Avi Kivity 已提交
1892
    hwaddr page;
1893
    MemoryRegionSection *section;
1894

B
bellard 已提交
1895 1896 1897 1898 1899
    while (len > 0) {
        page = addr & TARGET_PAGE_MASK;
        l = (page + TARGET_PAGE_SIZE) - addr;
        if (l > len)
            l = len;
A
Avi Kivity 已提交
1900
        section = phys_page_find(d, page >> TARGET_PAGE_BITS);
1901

B
bellard 已提交
1902
        if (is_write) {
1903
            if (!memory_region_is_ram(section->mr)) {
A
Avi Kivity 已提交
1904
                hwaddr addr1;
1905
                addr1 = memory_region_section_addr(section, addr);
B
bellard 已提交
1906 1907
                /* XXX: could force cpu_single_env to NULL to avoid
                   potential bugs */
1908
                if (l >= 4 && ((addr1 & 3) == 0)) {
B
bellard 已提交
1909
                    /* 32 bit write access */
B
bellard 已提交
1910
                    val = ldl_p(buf);
1911
                    io_mem_write(section->mr, addr1, val, 4);
B
bellard 已提交
1912
                    l = 4;
1913
                } else if (l >= 2 && ((addr1 & 1) == 0)) {
B
bellard 已提交
1914
                    /* 16 bit write access */
B
bellard 已提交
1915
                    val = lduw_p(buf);
1916
                    io_mem_write(section->mr, addr1, val, 2);
B
bellard 已提交
1917 1918
                    l = 2;
                } else {
B
bellard 已提交
1919
                    /* 8 bit write access */
B
bellard 已提交
1920
                    val = ldub_p(buf);
1921
                    io_mem_write(section->mr, addr1, val, 1);
B
bellard 已提交
1922 1923
                    l = 1;
                }
1924
            } else if (!section->readonly) {
1925
                ram_addr_t addr1;
1926
                addr1 = memory_region_get_ram_addr(section->mr)
1927
                    + memory_region_section_addr(section, addr);
B
bellard 已提交
1928
                /* RAM case */
P
pbrook 已提交
1929
                ptr = qemu_get_ram_ptr(addr1);
B
bellard 已提交
1930
                memcpy(ptr, buf, l);
1931
                invalidate_and_set_dirty(addr1, l);
B
bellard 已提交
1932 1933
            }
        } else {
1934 1935
            if (!(memory_region_is_ram(section->mr) ||
                  memory_region_is_romd(section->mr))) {
A
Avi Kivity 已提交
1936
                hwaddr addr1;
B
bellard 已提交
1937
                /* I/O case */
1938
                addr1 = memory_region_section_addr(section, addr);
1939
                if (l >= 4 && ((addr1 & 3) == 0)) {
B
bellard 已提交
1940
                    /* 32 bit read access */
1941
                    val = io_mem_read(section->mr, addr1, 4);
B
bellard 已提交
1942
                    stl_p(buf, val);
B
bellard 已提交
1943
                    l = 4;
1944
                } else if (l >= 2 && ((addr1 & 1) == 0)) {
B
bellard 已提交
1945
                    /* 16 bit read access */
1946
                    val = io_mem_read(section->mr, addr1, 2);
B
bellard 已提交
1947
                    stw_p(buf, val);
B
bellard 已提交
1948 1949
                    l = 2;
                } else {
B
bellard 已提交
1950
                    /* 8 bit read access */
1951
                    val = io_mem_read(section->mr, addr1, 1);
B
bellard 已提交
1952
                    stb_p(buf, val);
B
bellard 已提交
1953 1954 1955 1956
                    l = 1;
                }
            } else {
                /* RAM case */
1957
                ptr = qemu_get_ram_ptr(section->mr->ram_addr
1958 1959
                                       + memory_region_section_addr(section,
                                                                    addr));
1960
                memcpy(buf, ptr, l);
B
bellard 已提交
1961 1962 1963 1964 1965 1966 1967
            }
        }
        len -= l;
        buf += l;
        addr += l;
    }
}
B
bellard 已提交
1968

A
Avi Kivity 已提交
1969
void address_space_write(AddressSpace *as, hwaddr addr,
A
Avi Kivity 已提交
1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981
                         const uint8_t *buf, int len)
{
    address_space_rw(as, addr, (uint8_t *)buf, len, true);
}

/**
 * address_space_read: read from an address space.
 *
 * @as: #AddressSpace to be accessed
 * @addr: address within that address space
 * @buf: buffer with the data transferred
 */
A
Avi Kivity 已提交
1982
void address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len)
A
Avi Kivity 已提交
1983 1984 1985 1986 1987
{
    address_space_rw(as, addr, buf, len, false);
}


A
Avi Kivity 已提交
1988
void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
A
Avi Kivity 已提交
1989 1990 1991 1992 1993
                            int len, int is_write)
{
    return address_space_rw(&address_space_memory, addr, buf, len, is_write);
}

B
bellard 已提交
1994
/* used for ROM loading : can write in RAM and ROM */
A
Avi Kivity 已提交
1995
void cpu_physical_memory_write_rom(hwaddr addr,
B
bellard 已提交
1996 1997
                                   const uint8_t *buf, int len)
{
A
Avi Kivity 已提交
1998
    AddressSpaceDispatch *d = address_space_memory.dispatch;
B
bellard 已提交
1999 2000
    int l;
    uint8_t *ptr;
A
Avi Kivity 已提交
2001
    hwaddr page;
2002
    MemoryRegionSection *section;
2003

B
bellard 已提交
2004 2005 2006 2007 2008
    while (len > 0) {
        page = addr & TARGET_PAGE_MASK;
        l = (page + TARGET_PAGE_SIZE) - addr;
        if (l > len)
            l = len;
A
Avi Kivity 已提交
2009
        section = phys_page_find(d, page >> TARGET_PAGE_BITS);
2010

2011 2012
        if (!(memory_region_is_ram(section->mr) ||
              memory_region_is_romd(section->mr))) {
B
bellard 已提交
2013 2014 2015
            /* do nothing */
        } else {
            unsigned long addr1;
2016
            addr1 = memory_region_get_ram_addr(section->mr)
2017
                + memory_region_section_addr(section, addr);
B
bellard 已提交
2018
            /* ROM/RAM case */
P
pbrook 已提交
2019
            ptr = qemu_get_ram_ptr(addr1);
B
bellard 已提交
2020
            memcpy(ptr, buf, l);
2021
            invalidate_and_set_dirty(addr1, l);
B
bellard 已提交
2022 2023 2024 2025 2026 2027 2028
        }
        len -= l;
        buf += l;
        addr += l;
    }
}

2029 2030
typedef struct {
    void *buffer;
A
Avi Kivity 已提交
2031 2032
    hwaddr addr;
    hwaddr len;
2033 2034 2035 2036
} BounceBuffer;

static BounceBuffer bounce;

2037 2038 2039
typedef struct MapClient {
    void *opaque;
    void (*callback)(void *opaque);
B
Blue Swirl 已提交
2040
    QLIST_ENTRY(MapClient) link;
2041 2042
} MapClient;

B
Blue Swirl 已提交
2043 2044
static QLIST_HEAD(map_client_list, MapClient) map_client_list
    = QLIST_HEAD_INITIALIZER(map_client_list);
2045 2046 2047

void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
{
2048
    MapClient *client = g_malloc(sizeof(*client));
2049 2050 2051

    client->opaque = opaque;
    client->callback = callback;
B
Blue Swirl 已提交
2052
    QLIST_INSERT_HEAD(&map_client_list, client, link);
2053 2054 2055
    return client;
}

B
Blue Swirl 已提交
2056
static void cpu_unregister_map_client(void *_client)
2057 2058 2059
{
    MapClient *client = (MapClient *)_client;

B
Blue Swirl 已提交
2060
    QLIST_REMOVE(client, link);
2061
    g_free(client);
2062 2063 2064 2065 2066 2067
}

static void cpu_notify_map_clients(void)
{
    MapClient *client;

B
Blue Swirl 已提交
2068 2069
    while (!QLIST_EMPTY(&map_client_list)) {
        client = QLIST_FIRST(&map_client_list);
2070
        client->callback(client->opaque);
2071
        cpu_unregister_map_client(client);
2072 2073 2074
    }
}

2075 2076 2077 2078
/* Map a physical memory region into a host virtual address.
 * May map a subset of the requested range, given by and returned in *plen.
 * May return NULL if resources needed to perform the mapping are exhausted.
 * Use only for reads OR writes - not for read-modify-write operations.
2079 2080
 * Use cpu_register_map_client() to know when retrying the map operation is
 * likely to succeed.
2081
 */
A
Avi Kivity 已提交
2082
void *address_space_map(AddressSpace *as,
A
Avi Kivity 已提交
2083 2084
                        hwaddr addr,
                        hwaddr *plen,
A
Avi Kivity 已提交
2085
                        bool is_write)
2086
{
A
Avi Kivity 已提交
2087
    AddressSpaceDispatch *d = as->dispatch;
A
Avi Kivity 已提交
2088 2089
    hwaddr len = *plen;
    hwaddr todo = 0;
2090
    int l;
A
Avi Kivity 已提交
2091
    hwaddr page;
2092
    MemoryRegionSection *section;
2093
    ram_addr_t raddr = RAM_ADDR_MAX;
2094 2095
    ram_addr_t rlen;
    void *ret;
2096 2097 2098 2099 2100 2101

    while (len > 0) {
        page = addr & TARGET_PAGE_MASK;
        l = (page + TARGET_PAGE_SIZE) - addr;
        if (l > len)
            l = len;
A
Avi Kivity 已提交
2102
        section = phys_page_find(d, page >> TARGET_PAGE_BITS);
2103

2104
        if (!(memory_region_is_ram(section->mr) && !section->readonly)) {
2105
            if (todo || bounce.buffer) {
2106 2107 2108 2109 2110 2111
                break;
            }
            bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
            bounce.addr = addr;
            bounce.len = l;
            if (!is_write) {
A
Avi Kivity 已提交
2112
                address_space_read(as, addr, bounce.buffer, l);
2113
            }
2114 2115 2116

            *plen = l;
            return bounce.buffer;
2117
        }
2118
        if (!todo) {
2119
            raddr = memory_region_get_ram_addr(section->mr)
2120
                + memory_region_section_addr(section, addr);
2121
        }
2122 2123 2124

        len -= l;
        addr += l;
2125
        todo += l;
2126
    }
2127 2128 2129 2130
    rlen = todo;
    ret = qemu_ram_ptr_length(raddr, &rlen);
    *plen = rlen;
    return ret;
2131 2132
}

A
Avi Kivity 已提交
2133
/* Unmaps a memory region previously mapped by address_space_map().
2134 2135 2136
 * Will also mark the memory as dirty if is_write == 1.  access_len gives
 * the amount of memory that was actually read or written by the caller.
 */
A
Avi Kivity 已提交
2137 2138
void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
                         int is_write, hwaddr access_len)
2139 2140 2141
{
    if (buffer != bounce.buffer) {
        if (is_write) {
M
Marcelo Tosatti 已提交
2142
            ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
2143 2144 2145 2146 2147
            while (access_len) {
                unsigned l;
                l = TARGET_PAGE_SIZE;
                if (l > access_len)
                    l = access_len;
2148
                invalidate_and_set_dirty(addr1, l);
2149 2150 2151 2152
                addr1 += l;
                access_len -= l;
            }
        }
2153
        if (xen_enabled()) {
J
Jan Kiszka 已提交
2154
            xen_invalidate_map_cache_entry(buffer);
A
Anthony PERARD 已提交
2155
        }
2156 2157 2158
        return;
    }
    if (is_write) {
A
Avi Kivity 已提交
2159
        address_space_write(as, bounce.addr, bounce.buffer, access_len);
2160
    }
2161
    qemu_vfree(bounce.buffer);
2162
    bounce.buffer = NULL;
2163
    cpu_notify_map_clients();
2164
}
B
bellard 已提交
2165

A
Avi Kivity 已提交
2166 2167
void *cpu_physical_memory_map(hwaddr addr,
                              hwaddr *plen,
A
Avi Kivity 已提交
2168 2169 2170 2171 2172
                              int is_write)
{
    return address_space_map(&address_space_memory, addr, plen, is_write);
}

A
Avi Kivity 已提交
2173 2174
void cpu_physical_memory_unmap(void *buffer, hwaddr len,
                               int is_write, hwaddr access_len)
A
Avi Kivity 已提交
2175 2176 2177 2178
{
    return address_space_unmap(&address_space_memory, buffer, len, is_write, access_len);
}

B
bellard 已提交
2179
/* warning: addr must be aligned */
A
Avi Kivity 已提交
2180
static inline uint32_t ldl_phys_internal(hwaddr addr,
2181
                                         enum device_endian endian)
B
bellard 已提交
2182 2183 2184
{
    uint8_t *ptr;
    uint32_t val;
2185
    MemoryRegionSection *section;
B
bellard 已提交
2186

A
Avi Kivity 已提交
2187
    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
2188

2189 2190
    if (!(memory_region_is_ram(section->mr) ||
          memory_region_is_romd(section->mr))) {
B
bellard 已提交
2191
        /* I/O case */
2192
        addr = memory_region_section_addr(section, addr);
2193
        val = io_mem_read(section->mr, addr, 4);
2194 2195 2196 2197 2198 2199 2200 2201 2202
#if defined(TARGET_WORDS_BIGENDIAN)
        if (endian == DEVICE_LITTLE_ENDIAN) {
            val = bswap32(val);
        }
#else
        if (endian == DEVICE_BIG_ENDIAN) {
            val = bswap32(val);
        }
#endif
B
bellard 已提交
2203 2204
    } else {
        /* RAM case */
2205
        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
2206
                                & TARGET_PAGE_MASK)
2207
                               + memory_region_section_addr(section, addr));
2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218
        switch (endian) {
        case DEVICE_LITTLE_ENDIAN:
            val = ldl_le_p(ptr);
            break;
        case DEVICE_BIG_ENDIAN:
            val = ldl_be_p(ptr);
            break;
        default:
            val = ldl_p(ptr);
            break;
        }
B
bellard 已提交
2219 2220 2221 2222
    }
    return val;
}

A
Avi Kivity 已提交
2223
uint32_t ldl_phys(hwaddr addr)
2224 2225 2226 2227
{
    return ldl_phys_internal(addr, DEVICE_NATIVE_ENDIAN);
}

A
Avi Kivity 已提交
2228
uint32_t ldl_le_phys(hwaddr addr)
2229 2230 2231 2232
{
    return ldl_phys_internal(addr, DEVICE_LITTLE_ENDIAN);
}

A
Avi Kivity 已提交
2233
uint32_t ldl_be_phys(hwaddr addr)
2234 2235 2236 2237
{
    return ldl_phys_internal(addr, DEVICE_BIG_ENDIAN);
}

B
bellard 已提交
2238
/* warning: addr must be aligned */
A
Avi Kivity 已提交
2239
static inline uint64_t ldq_phys_internal(hwaddr addr,
2240
                                         enum device_endian endian)
B
bellard 已提交
2241 2242 2243
{
    uint8_t *ptr;
    uint64_t val;
2244
    MemoryRegionSection *section;
B
bellard 已提交
2245

A
Avi Kivity 已提交
2246
    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
2247

2248 2249
    if (!(memory_region_is_ram(section->mr) ||
          memory_region_is_romd(section->mr))) {
B
bellard 已提交
2250
        /* I/O case */
2251
        addr = memory_region_section_addr(section, addr);
2252 2253 2254

        /* XXX This is broken when device endian != cpu endian.
               Fix and add "endian" variable check */
B
bellard 已提交
2255
#ifdef TARGET_WORDS_BIGENDIAN
2256 2257
        val = io_mem_read(section->mr, addr, 4) << 32;
        val |= io_mem_read(section->mr, addr + 4, 4);
B
bellard 已提交
2258
#else
2259 2260
        val = io_mem_read(section->mr, addr, 4);
        val |= io_mem_read(section->mr, addr + 4, 4) << 32;
B
bellard 已提交
2261 2262 2263
#endif
    } else {
        /* RAM case */
2264
        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
2265
                                & TARGET_PAGE_MASK)
2266
                               + memory_region_section_addr(section, addr));
2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277
        switch (endian) {
        case DEVICE_LITTLE_ENDIAN:
            val = ldq_le_p(ptr);
            break;
        case DEVICE_BIG_ENDIAN:
            val = ldq_be_p(ptr);
            break;
        default:
            val = ldq_p(ptr);
            break;
        }
B
bellard 已提交
2278 2279 2280 2281
    }
    return val;
}

A
Avi Kivity 已提交
2282
uint64_t ldq_phys(hwaddr addr)
2283 2284 2285 2286
{
    return ldq_phys_internal(addr, DEVICE_NATIVE_ENDIAN);
}

A
Avi Kivity 已提交
2287
uint64_t ldq_le_phys(hwaddr addr)
2288 2289 2290 2291
{
    return ldq_phys_internal(addr, DEVICE_LITTLE_ENDIAN);
}

A
Avi Kivity 已提交
2292
uint64_t ldq_be_phys(hwaddr addr)
2293 2294 2295 2296
{
    return ldq_phys_internal(addr, DEVICE_BIG_ENDIAN);
}

B
bellard 已提交
2297
/* XXX: optimize */
A
Avi Kivity 已提交
2298
uint32_t ldub_phys(hwaddr addr)
B
bellard 已提交
2299 2300 2301 2302 2303 2304
{
    uint8_t val;
    cpu_physical_memory_read(addr, &val, 1);
    return val;
}

2305
/* warning: addr must be aligned */
A
Avi Kivity 已提交
2306
static inline uint32_t lduw_phys_internal(hwaddr addr,
2307
                                          enum device_endian endian)
B
bellard 已提交
2308
{
2309 2310
    uint8_t *ptr;
    uint64_t val;
2311
    MemoryRegionSection *section;
2312

A
Avi Kivity 已提交
2313
    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
2314

2315 2316
    if (!(memory_region_is_ram(section->mr) ||
          memory_region_is_romd(section->mr))) {
2317
        /* I/O case */
2318
        addr = memory_region_section_addr(section, addr);
2319
        val = io_mem_read(section->mr, addr, 2);
2320 2321 2322 2323 2324 2325 2326 2327 2328
#if defined(TARGET_WORDS_BIGENDIAN)
        if (endian == DEVICE_LITTLE_ENDIAN) {
            val = bswap16(val);
        }
#else
        if (endian == DEVICE_BIG_ENDIAN) {
            val = bswap16(val);
        }
#endif
2329 2330
    } else {
        /* RAM case */
2331
        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
2332
                                & TARGET_PAGE_MASK)
2333
                               + memory_region_section_addr(section, addr));
2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344
        switch (endian) {
        case DEVICE_LITTLE_ENDIAN:
            val = lduw_le_p(ptr);
            break;
        case DEVICE_BIG_ENDIAN:
            val = lduw_be_p(ptr);
            break;
        default:
            val = lduw_p(ptr);
            break;
        }
2345 2346
    }
    return val;
B
bellard 已提交
2347 2348
}

A
Avi Kivity 已提交
2349
uint32_t lduw_phys(hwaddr addr)
2350 2351 2352 2353
{
    return lduw_phys_internal(addr, DEVICE_NATIVE_ENDIAN);
}

A
Avi Kivity 已提交
2354
uint32_t lduw_le_phys(hwaddr addr)
2355 2356 2357 2358
{
    return lduw_phys_internal(addr, DEVICE_LITTLE_ENDIAN);
}

A
Avi Kivity 已提交
2359
uint32_t lduw_be_phys(hwaddr addr)
2360 2361 2362 2363
{
    return lduw_phys_internal(addr, DEVICE_BIG_ENDIAN);
}

B
bellard 已提交
2364 2365 2366
/* warning: addr must be aligned. The ram page is not masked as dirty
   and the code inside is not invalidated. It is useful if the dirty
   bits are used to track modified PTEs */
A
Avi Kivity 已提交
2367
void stl_phys_notdirty(hwaddr addr, uint32_t val)
B
bellard 已提交
2368 2369
{
    uint8_t *ptr;
2370
    MemoryRegionSection *section;
B
bellard 已提交
2371

A
Avi Kivity 已提交
2372
    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
2373

2374
    if (!memory_region_is_ram(section->mr) || section->readonly) {
2375
        addr = memory_region_section_addr(section, addr);
2376
        if (memory_region_is_ram(section->mr)) {
2377
            section = &phys_sections[phys_section_rom];
2378
        }
2379
        io_mem_write(section->mr, addr, val, 4);
B
bellard 已提交
2380
    } else {
2381
        unsigned long addr1 = (memory_region_get_ram_addr(section->mr)
2382
                               & TARGET_PAGE_MASK)
2383
            + memory_region_section_addr(section, addr);
P
pbrook 已提交
2384
        ptr = qemu_get_ram_ptr(addr1);
B
bellard 已提交
2385
        stl_p(ptr, val);
A
aliguori 已提交
2386 2387 2388 2389 2390 2391

        if (unlikely(in_migration)) {
            if (!cpu_physical_memory_is_dirty(addr1)) {
                /* invalidate code */
                tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
                /* set dirty bit */
2392 2393
                cpu_physical_memory_set_dirty_flags(
                    addr1, (0xff & ~CODE_DIRTY_FLAG));
A
aliguori 已提交
2394 2395
            }
        }
B
bellard 已提交
2396 2397 2398 2399
    }
}

/* warning: addr must be aligned */
A
Avi Kivity 已提交
2400
static inline void stl_phys_internal(hwaddr addr, uint32_t val,
2401
                                     enum device_endian endian)
B
bellard 已提交
2402 2403
{
    uint8_t *ptr;
2404
    MemoryRegionSection *section;
B
bellard 已提交
2405

A
Avi Kivity 已提交
2406
    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
2407

2408
    if (!memory_region_is_ram(section->mr) || section->readonly) {
2409
        addr = memory_region_section_addr(section, addr);
2410
        if (memory_region_is_ram(section->mr)) {
2411
            section = &phys_sections[phys_section_rom];
2412
        }
2413 2414 2415 2416 2417 2418 2419 2420 2421
#if defined(TARGET_WORDS_BIGENDIAN)
        if (endian == DEVICE_LITTLE_ENDIAN) {
            val = bswap32(val);
        }
#else
        if (endian == DEVICE_BIG_ENDIAN) {
            val = bswap32(val);
        }
#endif
2422
        io_mem_write(section->mr, addr, val, 4);
B
bellard 已提交
2423 2424
    } else {
        unsigned long addr1;
2425
        addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
2426
            + memory_region_section_addr(section, addr);
B
bellard 已提交
2427
        /* RAM case */
P
pbrook 已提交
2428
        ptr = qemu_get_ram_ptr(addr1);
2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439
        switch (endian) {
        case DEVICE_LITTLE_ENDIAN:
            stl_le_p(ptr, val);
            break;
        case DEVICE_BIG_ENDIAN:
            stl_be_p(ptr, val);
            break;
        default:
            stl_p(ptr, val);
            break;
        }
2440
        invalidate_and_set_dirty(addr1, 4);
B
bellard 已提交
2441 2442 2443
    }
}

A
Avi Kivity 已提交
2444
void stl_phys(hwaddr addr, uint32_t val)
2445 2446 2447 2448
{
    stl_phys_internal(addr, val, DEVICE_NATIVE_ENDIAN);
}

A
Avi Kivity 已提交
2449
void stl_le_phys(hwaddr addr, uint32_t val)
2450 2451 2452 2453
{
    stl_phys_internal(addr, val, DEVICE_LITTLE_ENDIAN);
}

A
Avi Kivity 已提交
2454
void stl_be_phys(hwaddr addr, uint32_t val)
2455 2456 2457 2458
{
    stl_phys_internal(addr, val, DEVICE_BIG_ENDIAN);
}

B
bellard 已提交
2459
/* XXX: optimize */
A
Avi Kivity 已提交
2460
void stb_phys(hwaddr addr, uint32_t val)
B
bellard 已提交
2461 2462 2463 2464 2465
{
    uint8_t v = val;
    cpu_physical_memory_write(addr, &v, 1);
}

2466
/* warning: addr must be aligned */
A
Avi Kivity 已提交
2467
static inline void stw_phys_internal(hwaddr addr, uint32_t val,
2468
                                     enum device_endian endian)
B
bellard 已提交
2469
{
2470
    uint8_t *ptr;
2471
    MemoryRegionSection *section;
2472

A
Avi Kivity 已提交
2473
    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
2474

2475
    if (!memory_region_is_ram(section->mr) || section->readonly) {
2476
        addr = memory_region_section_addr(section, addr);
2477
        if (memory_region_is_ram(section->mr)) {
2478
            section = &phys_sections[phys_section_rom];
2479
        }
2480 2481 2482 2483 2484 2485 2486 2487 2488
#if defined(TARGET_WORDS_BIGENDIAN)
        if (endian == DEVICE_LITTLE_ENDIAN) {
            val = bswap16(val);
        }
#else
        if (endian == DEVICE_BIG_ENDIAN) {
            val = bswap16(val);
        }
#endif
2489
        io_mem_write(section->mr, addr, val, 2);
2490 2491
    } else {
        unsigned long addr1;
2492
        addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
2493
            + memory_region_section_addr(section, addr);
2494 2495
        /* RAM case */
        ptr = qemu_get_ram_ptr(addr1);
2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506
        switch (endian) {
        case DEVICE_LITTLE_ENDIAN:
            stw_le_p(ptr, val);
            break;
        case DEVICE_BIG_ENDIAN:
            stw_be_p(ptr, val);
            break;
        default:
            stw_p(ptr, val);
            break;
        }
2507
        invalidate_and_set_dirty(addr1, 2);
2508
    }
B
bellard 已提交
2509 2510
}

A
Avi Kivity 已提交
2511
void stw_phys(hwaddr addr, uint32_t val)
2512 2513 2514 2515
{
    stw_phys_internal(addr, val, DEVICE_NATIVE_ENDIAN);
}

A
Avi Kivity 已提交
2516
void stw_le_phys(hwaddr addr, uint32_t val)
2517 2518 2519 2520
{
    stw_phys_internal(addr, val, DEVICE_LITTLE_ENDIAN);
}

A
Avi Kivity 已提交
2521
void stw_be_phys(hwaddr addr, uint32_t val)
2522 2523 2524 2525
{
    stw_phys_internal(addr, val, DEVICE_BIG_ENDIAN);
}

B
bellard 已提交
2526
/* XXX: optimize */
A
Avi Kivity 已提交
2527
void stq_phys(hwaddr addr, uint64_t val)
B
bellard 已提交
2528 2529
{
    val = tswap64(val);
2530
    cpu_physical_memory_write(addr, &val, 8);
B
bellard 已提交
2531 2532
}

A
Avi Kivity 已提交
2533
void stq_le_phys(hwaddr addr, uint64_t val)
2534 2535 2536 2537 2538
{
    val = cpu_to_le64(val);
    cpu_physical_memory_write(addr, &val, 8);
}

A
Avi Kivity 已提交
2539
void stq_be_phys(hwaddr addr, uint64_t val)
2540 2541 2542 2543 2544
{
    val = cpu_to_be64(val);
    cpu_physical_memory_write(addr, &val, 8);
}

2545
/* virtual memory access for debug (includes writing to ROM) */
2546
int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
2547
                        uint8_t *buf, int len, int is_write)
B
bellard 已提交
2548 2549
{
    int l;
A
Avi Kivity 已提交
2550
    hwaddr phys_addr;
2551
    target_ulong page;
B
bellard 已提交
2552 2553 2554 2555 2556 2557 2558 2559 2560 2561

    while (len > 0) {
        page = addr & TARGET_PAGE_MASK;
        phys_addr = cpu_get_phys_page_debug(env, page);
        /* if no physical page mapped, return an error */
        if (phys_addr == -1)
            return -1;
        l = (page + TARGET_PAGE_SIZE) - addr;
        if (l > len)
            l = len;
2562 2563 2564 2565 2566
        phys_addr += (addr & ~TARGET_PAGE_MASK);
        if (is_write)
            cpu_physical_memory_write_rom(phys_addr, buf, l);
        else
            cpu_physical_memory_rw(phys_addr, buf, l, is_write);
B
bellard 已提交
2567 2568 2569 2570 2571 2572
        len -= l;
        buf += l;
        addr += l;
    }
    return 0;
}
P
Paul Brook 已提交
2573
#endif
B
bellard 已提交
2574

2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592
#if !defined(CONFIG_USER_ONLY)

/*
 * A helper function for the _utterly broken_ virtio device model to find out if
 * it's running on a big endian machine. Don't do this at home kids!
 */
bool virtio_is_big_endian(void);
bool virtio_is_big_endian(void)
{
#if defined(TARGET_WORDS_BIGENDIAN)
    return true;
#else
    return false;
#endif
}

#endif

2593
#ifndef CONFIG_USER_ONLY
A
Avi Kivity 已提交
2594
bool cpu_physical_memory_is_io(hwaddr phys_addr)
2595 2596 2597
{
    MemoryRegionSection *section;

A
Avi Kivity 已提交
2598 2599
    section = phys_page_find(address_space_memory.dispatch,
                             phys_addr >> TARGET_PAGE_BITS);
2600 2601 2602 2603 2604

    return !(memory_region_is_ram(section->mr) ||
             memory_region_is_romd(section->mr));
}
#endif