exec.c 74.1 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
void cpu_exec_init(CPUArchState *env)
B
bellard 已提交
269
{
270
    CPUState *cpu = ENV_GET_CPU(env);
271
    CPUClass *cc = CPU_GET_CLASS(cpu);
272 273 274 275 276 277 278 279 280 281 282 283 284
    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++;
    }
285
    cpu->cpu_index = cpu_index;
286
    cpu->numa_node = 0;
287 288 289 290 291 292 293 294 295
    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
296
    vmstate_register(NULL, cpu_index, &vmstate_cpu_common, cpu);
297 298 299
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
    register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
                    cpu_save, cpu_load, env);
300
    assert(cc->vmsd == NULL);
301
#endif
302 303 304
    if (cc->vmsd != NULL) {
        vmstate_register(NULL, cpu_index, cc->vmsd, cpu);
    }
B
bellard 已提交
305 306
}

B
bellard 已提交
307
#if defined(TARGET_HAS_ICE)
308
#if defined(CONFIG_USER_ONLY)
309
static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
310 311 312 313
{
    tb_invalidate_phys_page_range(pc, pc + 1, 0);
}
#else
314 315
static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
{
316 317
    tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc) |
            (pc & ~TARGET_PAGE_MASK));
318
}
B
bellard 已提交
319
#endif
320
#endif /* TARGET_HAS_ICE */
B
bellard 已提交
321

322
#if defined(CONFIG_USER_ONLY)
323
void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
324 325 326 327

{
}

328
int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
329 330 331 332 333
                          int flags, CPUWatchpoint **watchpoint)
{
    return -ENOSYS;
}
#else
334
/* Add a watchpoint.  */
335
int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
336
                          int flags, CPUWatchpoint **watchpoint)
337
{
338
    target_ulong len_mask = ~(len - 1);
339
    CPUWatchpoint *wp;
340

341
    /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
342 343
    if ((len & (len - 1)) || (addr & ~len_mask) ||
            len == 0 || len > TARGET_PAGE_SIZE) {
344 345 346 347
        fprintf(stderr, "qemu: tried to set invalid watchpoint at "
                TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
        return -EINVAL;
    }
348
    wp = g_malloc(sizeof(*wp));
349 350

    wp->vaddr = addr;
351
    wp->len_mask = len_mask;
352 353
    wp->flags = flags;

354
    /* keep all GDB-injected watchpoints in front */
355
    if (flags & BP_GDB)
B
Blue Swirl 已提交
356
        QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
357
    else
B
Blue Swirl 已提交
358
        QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
359 360

    tlb_flush_page(env, addr);
361 362 363 364

    if (watchpoint)
        *watchpoint = wp;
    return 0;
365 366
}

367
/* Remove a specific watchpoint.  */
368
int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
369
                          int flags)
370
{
371
    target_ulong len_mask = ~(len - 1);
372
    CPUWatchpoint *wp;
373

B
Blue Swirl 已提交
374
    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
375
        if (addr == wp->vaddr && len_mask == wp->len_mask
376
                && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
377
            cpu_watchpoint_remove_by_ref(env, wp);
378 379 380
            return 0;
        }
    }
381
    return -ENOENT;
382 383
}

384
/* Remove a specific watchpoint by reference.  */
385
void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
386
{
B
Blue Swirl 已提交
387
    QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
388

389 390
    tlb_flush_page(env, watchpoint->vaddr);

391
    g_free(watchpoint);
392 393 394
}

/* Remove all matching watchpoints.  */
395
void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
396
{
397
    CPUWatchpoint *wp, *next;
398

B
Blue Swirl 已提交
399
    QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
400 401
        if (wp->flags & mask)
            cpu_watchpoint_remove_by_ref(env, wp);
402
    }
403
}
404
#endif
405

406
/* Add a breakpoint.  */
407
int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
408
                          CPUBreakpoint **breakpoint)
B
bellard 已提交
409
{
B
bellard 已提交
410
#if defined(TARGET_HAS_ICE)
411
    CPUBreakpoint *bp;
412

413
    bp = g_malloc(sizeof(*bp));
B
bellard 已提交
414

415 416 417
    bp->pc = pc;
    bp->flags = flags;

418
    /* keep all GDB-injected breakpoints in front */
419
    if (flags & BP_GDB)
B
Blue Swirl 已提交
420
        QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
421
    else
B
Blue Swirl 已提交
422
        QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
423

B
bellard 已提交
424
    breakpoint_invalidate(env, pc);
425 426 427

    if (breakpoint)
        *breakpoint = bp;
B
bellard 已提交
428 429
    return 0;
#else
430
    return -ENOSYS;
B
bellard 已提交
431 432 433
#endif
}

434
/* Remove a specific breakpoint.  */
435
int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
436
{
437
#if defined(TARGET_HAS_ICE)
438 439
    CPUBreakpoint *bp;

B
Blue Swirl 已提交
440
    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
441 442 443 444
        if (bp->pc == pc && bp->flags == flags) {
            cpu_breakpoint_remove_by_ref(env, bp);
            return 0;
        }
445
    }
446 447 448
    return -ENOENT;
#else
    return -ENOSYS;
449 450 451
#endif
}

452
/* Remove a specific breakpoint by reference.  */
453
void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
B
bellard 已提交
454
{
B
bellard 已提交
455
#if defined(TARGET_HAS_ICE)
B
Blue Swirl 已提交
456
    QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
B
bellard 已提交
457

458 459
    breakpoint_invalidate(env, breakpoint->pc);

460
    g_free(breakpoint);
461 462 463 464
#endif
}

/* Remove all matching breakpoints. */
465
void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
466 467
{
#if defined(TARGET_HAS_ICE)
468
    CPUBreakpoint *bp, *next;
469

B
Blue Swirl 已提交
470
    QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
471 472
        if (bp->flags & mask)
            cpu_breakpoint_remove_by_ref(env, bp);
473
    }
B
bellard 已提交
474 475 476
#endif
}

B
bellard 已提交
477 478
/* enable or disable single step mode. EXCP_DEBUG is returned by the
   CPU loop after each instruction */
479
void cpu_single_step(CPUArchState *env, int enabled)
B
bellard 已提交
480
{
B
bellard 已提交
481
#if defined(TARGET_HAS_ICE)
B
bellard 已提交
482 483
    if (env->singlestep_enabled != enabled) {
        env->singlestep_enabled = enabled;
484 485 486
        if (kvm_enabled())
            kvm_update_guest_debug(env, 0);
        else {
S
Stuart Brady 已提交
487
            /* must flush all the translated code to avoid inconsistencies */
488 489 490
            /* XXX: only flush what is necessary */
            tb_flush(env);
        }
B
bellard 已提交
491 492 493 494
    }
#endif
}

495
void cpu_exit(CPUArchState *env)
496
{
497 498 499
    CPUState *cpu = ENV_GET_CPU(env);

    cpu->exit_request = 1;
500
    cpu->tcg_exit_req = 1;
501 502
}

503
void cpu_abort(CPUArchState *env, const char *fmt, ...)
B
bellard 已提交
504 505
{
    va_list ap;
P
pbrook 已提交
506
    va_list ap2;
B
bellard 已提交
507 508

    va_start(ap, fmt);
P
pbrook 已提交
509
    va_copy(ap2, ap);
B
bellard 已提交
510 511 512
    fprintf(stderr, "qemu: fatal: ");
    vfprintf(stderr, fmt, ap);
    fprintf(stderr, "\n");
513
    cpu_dump_state(env, stderr, fprintf, CPU_DUMP_FPU | CPU_DUMP_CCOP);
514 515 516 517
    if (qemu_log_enabled()) {
        qemu_log("qemu: fatal: ");
        qemu_log_vprintf(fmt, ap2);
        qemu_log("\n");
518
        log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP);
519
        qemu_log_flush();
520
        qemu_log_close();
521
    }
P
pbrook 已提交
522
    va_end(ap2);
523
    va_end(ap);
524 525 526 527 528 529 530 531
#if defined(CONFIG_USER_ONLY)
    {
        struct sigaction act;
        sigfillset(&act.sa_mask);
        act.sa_handler = SIG_DFL;
        sigaction(SIGABRT, &act, NULL);
    }
#endif
B
bellard 已提交
532 533 534
    abort();
}

535
CPUArchState *cpu_copy(CPUArchState *env)
536
{
537 538
    CPUArchState *new_env = cpu_init(env->cpu_model_str);
    CPUArchState *next_cpu = new_env->next_cpu;
539 540 541 542 543
#if defined(TARGET_HAS_ICE)
    CPUBreakpoint *bp;
    CPUWatchpoint *wp;
#endif

544
    memcpy(new_env, env, sizeof(CPUArchState));
545

546
    /* Preserve chaining. */
547
    new_env->next_cpu = next_cpu;
548 549 550 551

    /* 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 已提交
552 553
    QTAILQ_INIT(&env->breakpoints);
    QTAILQ_INIT(&env->watchpoints);
554
#if defined(TARGET_HAS_ICE)
B
Blue Swirl 已提交
555
    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
556 557
        cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
    }
B
Blue Swirl 已提交
558
    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
559 560 561 562 563
        cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
                              wp->flags, NULL);
    }
#endif

564 565 566
    return new_env;
}

567
#if !defined(CONFIG_USER_ONLY)
J
Juan Quintela 已提交
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
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 已提交
586
/* Note: start and end must be within the same ram block.  */
A
Anthony Liguori 已提交
587
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
B
bellard 已提交
588
                                     int dirty_flags)
589
{
J
Juan Quintela 已提交
590
    uintptr_t length;
591 592 593 594 595 596 597

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

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

J
Juan Quintela 已提交
600 601
    if (tcg_enabled()) {
        tlb_reset_dirty_range_all(start, end, length);
P
pbrook 已提交
602
    }
603 604
}

B
Blue Swirl 已提交
605
static int cpu_physical_memory_set_dirty_tracking(int enable)
A
aliguori 已提交
606
{
M
Michael S. Tsirkin 已提交
607
    int ret = 0;
A
aliguori 已提交
608
    in_migration = enable;
M
Michael S. Tsirkin 已提交
609
    return ret;
A
aliguori 已提交
610 611
}

A
Avi Kivity 已提交
612
hwaddr memory_region_section_get_iotlb(CPUArchState *env,
B
Blue Swirl 已提交
613 614
                                                   MemoryRegionSection *section,
                                                   target_ulong vaddr,
A
Avi Kivity 已提交
615
                                                   hwaddr paddr,
B
Blue Swirl 已提交
616 617 618
                                                   int prot,
                                                   target_ulong *address)
{
A
Avi Kivity 已提交
619
    hwaddr iotlb;
B
Blue Swirl 已提交
620 621
    CPUWatchpoint *wp;

622
    if (memory_region_is_ram(section->mr)) {
B
Blue Swirl 已提交
623 624
        /* Normal RAM.  */
        iotlb = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
625
            + memory_region_section_addr(section, paddr);
B
Blue Swirl 已提交
626 627 628 629 630 631 632 633 634 635 636 637 638
        if (!section->readonly) {
            iotlb |= phys_section_notdirty;
        } else {
            iotlb |= phys_section_rom;
        }
    } else {
        /* IO handlers are currently passed a physical address.
           It would be nice to pass an offset from the base address
           of that region.  This would avoid having to special case RAM,
           and avoid full address decoding in every device.
           We can't use the high bits of pd for this because
           IO_MEM_ROMD uses these as a ram address.  */
        iotlb = section - phys_sections;
639
        iotlb += memory_region_section_addr(section, paddr);
B
Blue Swirl 已提交
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
    }

    /* 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;
}
657 658
#endif /* defined(CONFIG_USER_ONLY) */

659
#if !defined(CONFIG_USER_ONLY)
660

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

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

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

683
static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level)
684 685
{
    unsigned i;
686
    PhysPageEntry *p;
687

688
    if (lp->ptr == PHYS_MAP_NODE_NIL) {
689 690 691
        return;
    }

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

A
Avi Kivity 已提交
704
static void destroy_all_mappings(AddressSpaceDispatch *d)
705
{
A
Avi Kivity 已提交
706
    destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1);
707
    phys_map_nodes_reset();
708 709
}

710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
static uint16_t phys_section_add(MemoryRegionSection *section)
{
    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 已提交
726
static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *section)
727 728
{
    subpage_t *subpage;
A
Avi Kivity 已提交
729
    hwaddr base = section->offset_within_address_space
730
        & TARGET_PAGE_MASK;
A
Avi Kivity 已提交
731
    MemoryRegionSection *existing = phys_page_find(d, base >> TARGET_PAGE_BITS);
732 733 734 735
    MemoryRegionSection subsection = {
        .offset_within_address_space = base,
        .size = TARGET_PAGE_SIZE,
    };
A
Avi Kivity 已提交
736
    hwaddr start, end;
737

738
    assert(existing->mr->subpage || existing->mr == &io_mem_unassigned);
739

740
    if (!(existing->mr->subpage)) {
741 742
        subpage = subpage_init(base);
        subsection.mr = &subpage->iomem;
A
Avi Kivity 已提交
743
        phys_page_set(d, base >> TARGET_PAGE_BITS, 1,
744
                      phys_section_add(&subsection));
745
    } else {
746
        subpage = container_of(existing->mr, subpage_t, iomem);
747 748
    }
    start = section->offset_within_address_space & ~TARGET_PAGE_MASK;
749
    end = start + section->size - 1;
750 751 752 753
    subpage_register(subpage, start, end, phys_section_add(section));
}


A
Avi Kivity 已提交
754
static void register_multipage(AddressSpaceDispatch *d, MemoryRegionSection *section)
755
{
A
Avi Kivity 已提交
756
    hwaddr start_addr = section->offset_within_address_space;
757
    ram_addr_t size = section->size;
A
Avi Kivity 已提交
758
    hwaddr addr;
759
    uint16_t section_index = phys_section_add(section);
760

761
    assert(size);
M
Michael S. Tsirkin 已提交
762

763
    addr = start_addr;
A
Avi Kivity 已提交
764
    phys_page_set(d, addr >> TARGET_PAGE_BITS, size >> TARGET_PAGE_BITS,
765
                  section_index);
766 767
}

A
Avi Kivity 已提交
768
static void mem_add(MemoryListener *listener, MemoryRegionSection *section)
769
{
A
Avi Kivity 已提交
770
    AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener);
771 772 773 774 775 776 777
    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 已提交
778
        register_subpage(d, &now);
779 780 781 782
        remain.size -= now.size;
        remain.offset_within_address_space += now.size;
        remain.offset_within_region += now.size;
    }
783 784 785 786
    while (remain.size >= TARGET_PAGE_SIZE) {
        now = remain;
        if (remain.offset_within_region & ~TARGET_PAGE_MASK) {
            now.size = TARGET_PAGE_SIZE;
A
Avi Kivity 已提交
787
            register_subpage(d, &now);
788 789
        } else {
            now.size &= TARGET_PAGE_MASK;
A
Avi Kivity 已提交
790
            register_multipage(d, &now);
791
        }
792 793 794 795 796 797
        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 已提交
798
        register_subpage(d, &now);
799 800 801
    }
}

802 803 804 805 806 807
void qemu_flush_coalesced_mmio_buffer(void)
{
    if (kvm_enabled())
        kvm_flush_coalesced_mmio_buffer();
}

808 809 810 811 812 813 814 815 816 817
void qemu_mutex_lock_ramlist(void)
{
    qemu_mutex_lock(&ram_list.mutex);
}

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

818 819 820 821 822 823 824 825 826 827 828 829
#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 已提交
830
        ret = statfs(path, &fs);
831 832 833
    } while (ret != 0 && errno == EINTR);

    if (ret != 0) {
Y
Yoshiaki Tamura 已提交
834 835
        perror(path);
        return 0;
836 837 838
    }

    if (fs.f_type != HUGETLBFS_MAGIC)
Y
Yoshiaki Tamura 已提交
839
        fprintf(stderr, "Warning: path not on HugeTLBFS: %s\n", path);
840 841 842 843

    return fs.f_bsize;
}

A
Alex Williamson 已提交
844 845 846
static void *file_ram_alloc(RAMBlock *block,
                            ram_addr_t memory,
                            const char *path)
847 848
{
    char *filename;
849 850
    char *sanitized_name;
    char *c;
851 852 853 854 855 856 857 858 859
    void *area;
    int fd;
#ifdef MAP_POPULATE
    int flags;
#endif
    unsigned long hpagesize;

    hpagesize = gethugepagesize(path);
    if (!hpagesize) {
Y
Yoshiaki Tamura 已提交
860
        return NULL;
861 862 863 864 865 866 867 868 869 870 871
    }

    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;
    }

872 873 874 875 876 877 878 879 880 881
    /* 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);
882 883 884

    fd = mkstemp(filename);
    if (fd < 0) {
Y
Yoshiaki Tamura 已提交
885
        perror("unable to create backing store for hugepages");
886
        g_free(filename);
Y
Yoshiaki Tamura 已提交
887
        return NULL;
888 889
    }
    unlink(filename);
890
    g_free(filename);
891 892 893 894 895 896 897 898 899 900

    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 已提交
901
        perror("ftruncate");
902 903 904 905 906 907 908 909 910 911 912 913

#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 已提交
914 915 916
        perror("file_ram_alloc: can't mmap RAM pages");
        close(fd);
        return (NULL);
917
    }
A
Alex Williamson 已提交
918
    block->fd = fd;
919 920 921 922
    return area;
}
#endif

923
static ram_addr_t find_ram_offset(ram_addr_t size)
A
Alex Williamson 已提交
924 925
{
    RAMBlock *block, *next_block;
A
Alex Williamson 已提交
926
    ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX;
A
Alex Williamson 已提交
927

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

P
Paolo Bonzini 已提交
930
    if (QTAILQ_EMPTY(&ram_list.blocks))
A
Alex Williamson 已提交
931 932
        return 0;

P
Paolo Bonzini 已提交
933
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
934
        ram_addr_t end, next = RAM_ADDR_MAX;
A
Alex Williamson 已提交
935 936 937

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

P
Paolo Bonzini 已提交
938
        QTAILQ_FOREACH(next_block, &ram_list.blocks, next) {
A
Alex Williamson 已提交
939 940 941 942 943
            if (next_block->offset >= end) {
                next = MIN(next, next_block->offset);
            }
        }
        if (next - end >= size && next - end < mingap) {
A
Alex Williamson 已提交
944
            offset = end;
A
Alex Williamson 已提交
945 946 947
            mingap = next - end;
        }
    }
A
Alex Williamson 已提交
948 949 950 951 952 953 954

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

A
Alex Williamson 已提交
955 956 957
    return offset;
}

J
Juan Quintela 已提交
958
ram_addr_t last_ram_offset(void)
959 960 961 962
{
    RAMBlock *block;
    ram_addr_t last = 0;

P
Paolo Bonzini 已提交
963
    QTAILQ_FOREACH(block, &ram_list.blocks, next)
964 965 966 967 968
        last = MAX(last, block->offset + block->length);

    return last;
}

969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
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");
        }
    }
}

987
void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
988 989 990
{
    RAMBlock *new_block, *block;

991
    new_block = NULL;
P
Paolo Bonzini 已提交
992
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
993 994 995 996 997 998 999
        if (block->offset == addr) {
            new_block = block;
            break;
        }
    }
    assert(new_block);
    assert(!new_block->idstr[0]);
1000

1001 1002
    if (dev) {
        char *id = qdev_get_dev_path(dev);
1003 1004
        if (id) {
            snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
1005
            g_free(id);
1006 1007 1008 1009
        }
    }
    pstrcat(new_block->idstr, sizeof(new_block->idstr), name);

1010 1011
    /* This assumes the iothread lock is taken here too.  */
    qemu_mutex_lock_ramlist();
P
Paolo Bonzini 已提交
1012
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1013
        if (block != new_block && !strcmp(block->idstr, new_block->idstr)) {
1014 1015 1016 1017 1018
            fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
                    new_block->idstr);
            abort();
        }
    }
1019
    qemu_mutex_unlock_ramlist();
1020 1021
}

1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
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);
}

1035 1036 1037
ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
                                   MemoryRegion *mr)
{
1038
    RAMBlock *block, *new_block;
1039 1040 1041

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

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

1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
    /* 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);
    }
1087
    ram_list.mru_block = NULL;
P
pbrook 已提交
1088

U
Umesh Deshpande 已提交
1089
    ram_list.version++;
1090
    qemu_mutex_unlock_ramlist();
U
Umesh Deshpande 已提交
1091

1092
    ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
A
Alex Williamson 已提交
1093
                                       last_ram_offset() >> TARGET_PAGE_BITS);
1094 1095
    memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
           0, size >> TARGET_PAGE_BITS);
J
Juan Quintela 已提交
1096
    cpu_physical_memory_set_dirty_range(new_block->offset, size, 0xff);
P
pbrook 已提交
1097

1098
    qemu_ram_setup_dump(new_block->host, size);
1099
    qemu_madvise(new_block->host, size, QEMU_MADV_HUGEPAGE);
1100

1101 1102 1103
    if (kvm_enabled())
        kvm_setup_guest_memory(new_block->host, size);

P
pbrook 已提交
1104 1105
    return new_block->offset;
}
B
bellard 已提交
1106

1107
ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr)
1108
{
1109
    return qemu_ram_alloc_from_ptr(size, NULL, mr);
1110 1111
}

1112 1113 1114 1115
void qemu_ram_free_from_ptr(ram_addr_t addr)
{
    RAMBlock *block;

1116 1117
    /* This assumes the iothread lock is taken here too.  */
    qemu_mutex_lock_ramlist();
P
Paolo Bonzini 已提交
1118
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1119
        if (addr == block->offset) {
P
Paolo Bonzini 已提交
1120
            QTAILQ_REMOVE(&ram_list.blocks, block, next);
1121
            ram_list.mru_block = NULL;
U
Umesh Deshpande 已提交
1122
            ram_list.version++;
1123
            g_free(block);
1124
            break;
1125 1126
        }
    }
1127
    qemu_mutex_unlock_ramlist();
1128 1129
}

A
Anthony Liguori 已提交
1130
void qemu_ram_free(ram_addr_t addr)
B
bellard 已提交
1131
{
A
Alex Williamson 已提交
1132 1133
    RAMBlock *block;

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

B
bellard 已提交
1171 1172
}

H
Huang Ying 已提交
1173 1174 1175 1176 1177 1178 1179 1180
#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 已提交
1181
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
H
Huang Ying 已提交
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205
        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);
                    }
1206 1207
#else
                    abort();
H
Huang Ying 已提交
1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
#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) {
1221 1222
                    fprintf(stderr, "Could not remap addr: "
                            RAM_ADDR_FMT "@" RAM_ADDR_FMT "\n",
H
Huang Ying 已提交
1223 1224 1225
                            length, addr);
                    exit(1);
                }
1226
                memory_try_enable_merging(vaddr, length);
1227
                qemu_ram_setup_dump(vaddr, length);
H
Huang Ying 已提交
1228 1229 1230 1231 1232 1233 1234
            }
            return;
        }
    }
}
#endif /* !_WIN32 */

1235
/* Return a host pointer to ram allocated with qemu_ram_alloc.
P
pbrook 已提交
1236 1237 1238 1239 1240 1241 1242
   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 已提交
1243
void *qemu_get_ram_ptr(ram_addr_t addr)
1244
{
P
pbrook 已提交
1245 1246
    RAMBlock *block;

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

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

1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275
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);
1276 1277
}

1278 1279 1280 1281
/* 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?
1282
 */
B
Blue Swirl 已提交
1283
static void *qemu_safe_ram_ptr(ram_addr_t addr)
1284 1285 1286
{
    RAMBlock *block;

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

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

    return NULL;
}

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

P
Paolo Bonzini 已提交
1324
        QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
            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();
    }
}

A
Anthony PERARD 已提交
1337 1338 1339 1340 1341
void qemu_put_ram_ptr(void *addr)
{
    trace_qemu_put_ram_ptr(addr);
}

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

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

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

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

M
Marcelo Tosatti 已提交
1366 1367 1368 1369 1370
/* 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 已提交
1371

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

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

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

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

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

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

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

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

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

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

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

1479 1480 1481 1482
    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. */
1483
        cpu_interrupt(ENV_GET_CPU(env), CPU_INTERRUPT_DEBUG);
1484 1485
        return;
    }
P
pbrook 已提交
1486
    vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
B
Blue Swirl 已提交
1487
    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
1488 1489
        if ((vaddr == (wp->vaddr & len_mask) ||
             (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
1490 1491 1492
            wp->flags |= BP_WATCHPOINT_HIT;
            if (!env->watchpoint_hit) {
                env->watchpoint_hit = wp;
B
Blue Swirl 已提交
1493
                tb_check_watchpoint(env);
1494 1495
                if (wp->flags & BP_STOP_BEFORE_ACCESS) {
                    env->exception_index = EXCP_DEBUG;
1496
                    cpu_loop_exit(env);
1497 1498 1499
                } else {
                    cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
                    tb_gen_code(env, pc, cs_base, cpu_flags, 1);
1500
                    cpu_resume_from_signal(env, NULL);
1501
                }
1502
            }
1503 1504
        } else {
            wp->flags &= ~BP_WATCHPOINT_HIT;
P
pbrook 已提交
1505 1506 1507 1508
        }
    }
}

1509 1510 1511
/* 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 已提交
1512
static uint64_t watch_mem_read(void *opaque, hwaddr addr,
1513
                               unsigned size)
1514
{
1515 1516 1517 1518 1519 1520 1521
    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();
    }
1522 1523
}

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

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

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

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

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

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

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

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

A
Avi Kivity 已提交
1604
static void subpage_ram_write(void *opaque, hwaddr addr,
1605
                              uint64_t value, unsigned size)
1606 1607 1608
{
    ram_addr_t raddr = addr;
    void *ptr = qemu_get_ram_ptr(raddr);
1609 1610 1611 1612 1613 1614
    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();
    }
1615 1616
}

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

A
Anthony Liguori 已提交
1623
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
1624
                             uint16_t section)
1625 1626 1627 1628 1629 1630 1631 1632
{
    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)
1633
    printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
1634 1635
           mmio, start, end, idx, eidx, memory);
#endif
1636 1637 1638 1639
    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);
1640
    }
1641
    for (; idx <= eidx; idx++) {
1642
        mmio->sub_section[idx] = section;
1643 1644 1645 1646 1647
    }

    return 0;
}

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

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

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

    return mmio;
}

1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678
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 已提交
1679
MemoryRegion *iotlb_to_region(hwaddr index)
1680
{
1681
    return phys_sections[index & ~TARGET_PAGE_MASK].mr;
1682 1683
}

A
Avi Kivity 已提交
1684 1685
static void io_mem_init(void)
{
1686 1687 1688 1689 1690 1691
    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);
1692 1693
    memory_region_init_io(&io_mem_subpage_ram, &subpage_ram_ops, NULL,
                          "subpage-ram", UINT64_MAX);
1694 1695
    memory_region_init_io(&io_mem_watch, &watch_mem_ops, NULL,
                          "watch", UINT64_MAX);
A
Avi Kivity 已提交
1696 1697
}

A
Avi Kivity 已提交
1698 1699 1700 1701 1702 1703 1704 1705
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;
}

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

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

    /* 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);
    }
1725 1726
}

1727 1728 1729 1730 1731 1732 1733 1734 1735 1736
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);
}

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

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

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

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

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

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

A
Avi Kivity 已提交
1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786
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 已提交
1787 1788 1789 1790 1791 1792 1793 1794 1795 1796
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 已提交
1797 1798
static void memory_map_init(void)
{
1799
    system_memory = g_malloc(sizeof(*system_memory));
A
Avi Kivity 已提交
1800
    memory_region_init(system_memory, "system", INT64_MAX);
1801 1802
    address_space_init(&address_space_memory, system_memory);
    address_space_memory.name = "memory";
1803

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

1809 1810 1811
    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);
1812 1813 1814

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

MemoryRegion *get_system_memory(void)
{
    return system_memory;
}

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

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

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

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

B
bellard 已提交
1870
#else
1871

A
Avi Kivity 已提交
1872 1873
static void invalidate_and_set_dirty(hwaddr addr,
                                     hwaddr length)
1874 1875 1876 1877 1878 1879 1880
{
    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));
    }
1881
    xen_modified_memory(addr, length);
1882 1883
}

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

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

B
bellard 已提交
1901
        if (is_write) {
1902
            if (!memory_region_is_ram(section->mr)) {
A
Avi Kivity 已提交
1903
                hwaddr addr1;
1904
                addr1 = memory_region_section_addr(section, addr);
B
bellard 已提交
1905 1906
                /* XXX: could force cpu_single_env to NULL to avoid
                   potential bugs */
1907
                if (l >= 4 && ((addr1 & 3) == 0)) {
B
bellard 已提交
1908
                    /* 32 bit write access */
B
bellard 已提交
1909
                    val = ldl_p(buf);
1910
                    io_mem_write(section->mr, addr1, val, 4);
B
bellard 已提交
1911
                    l = 4;
1912
                } else if (l >= 2 && ((addr1 & 1) == 0)) {
B
bellard 已提交
1913
                    /* 16 bit write access */
B
bellard 已提交
1914
                    val = lduw_p(buf);
1915
                    io_mem_write(section->mr, addr1, val, 2);
B
bellard 已提交
1916 1917
                    l = 2;
                } else {
B
bellard 已提交
1918
                    /* 8 bit write access */
B
bellard 已提交
1919
                    val = ldub_p(buf);
1920
                    io_mem_write(section->mr, addr1, val, 1);
B
bellard 已提交
1921 1922
                    l = 1;
                }
1923
            } else if (!section->readonly) {
1924
                ram_addr_t addr1;
1925
                addr1 = memory_region_get_ram_addr(section->mr)
1926
                    + memory_region_section_addr(section, addr);
B
bellard 已提交
1927
                /* RAM case */
P
pbrook 已提交
1928
                ptr = qemu_get_ram_ptr(addr1);
B
bellard 已提交
1929
                memcpy(ptr, buf, l);
1930
                invalidate_and_set_dirty(addr1, l);
A
Anthony PERARD 已提交
1931
                qemu_put_ram_ptr(ptr);
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);
A
Anthony PERARD 已提交
1961
                qemu_put_ram_ptr(ptr);
B
bellard 已提交
1962 1963 1964 1965 1966 1967 1968
            }
        }
        len -= l;
        buf += l;
        addr += l;
    }
}
B
bellard 已提交
1969

A
Avi Kivity 已提交
1970
void address_space_write(AddressSpace *as, hwaddr addr,
A
Avi Kivity 已提交
1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982
                         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 已提交
1983
void address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len)
A
Avi Kivity 已提交
1984 1985 1986 1987 1988
{
    address_space_rw(as, addr, buf, len, false);
}


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

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

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

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

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

static BounceBuffer bounce;

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

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

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

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

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

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

static void cpu_notify_map_clients(void)
{
    MapClient *client;

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

2077 2078 2079 2080
/* 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.
2081 2082
 * Use cpu_register_map_client() to know when retrying the map operation is
 * likely to succeed.
2083
 */
A
Avi Kivity 已提交
2084
void *address_space_map(AddressSpace *as,
A
Avi Kivity 已提交
2085 2086
                        hwaddr addr,
                        hwaddr *plen,
A
Avi Kivity 已提交
2087
                        bool is_write)
2088
{
A
Avi Kivity 已提交
2089
    AddressSpaceDispatch *d = as->dispatch;
A
Avi Kivity 已提交
2090 2091
    hwaddr len = *plen;
    hwaddr todo = 0;
2092
    int l;
A
Avi Kivity 已提交
2093
    hwaddr page;
2094
    MemoryRegionSection *section;
2095
    ram_addr_t raddr = RAM_ADDR_MAX;
2096 2097
    ram_addr_t rlen;
    void *ret;
2098 2099 2100 2101 2102 2103

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

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

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

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

A
Avi Kivity 已提交
2135
/* Unmaps a memory region previously mapped by address_space_map().
2136 2137 2138
 * 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 已提交
2139 2140
void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
                         int is_write, hwaddr access_len)
2141 2142 2143
{
    if (buffer != bounce.buffer) {
        if (is_write) {
M
Marcelo Tosatti 已提交
2144
            ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
2145 2146 2147 2148 2149
            while (access_len) {
                unsigned l;
                l = TARGET_PAGE_SIZE;
                if (l > access_len)
                    l = access_len;
2150
                invalidate_and_set_dirty(addr1, l);
2151 2152 2153 2154
                addr1 += l;
                access_len -= l;
            }
        }
2155
        if (xen_enabled()) {
J
Jan Kiszka 已提交
2156
            xen_invalidate_map_cache_entry(buffer);
A
Anthony PERARD 已提交
2157
        }
2158 2159 2160
        return;
    }
    if (is_write) {
A
Avi Kivity 已提交
2161
        address_space_write(as, bounce.addr, bounce.buffer, access_len);
2162
    }
2163
    qemu_vfree(bounce.buffer);
2164
    bounce.buffer = NULL;
2165
    cpu_notify_map_clients();
2166
}
B
bellard 已提交
2167

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

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

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

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

2191 2192
    if (!(memory_region_is_ram(section->mr) ||
          memory_region_is_romd(section->mr))) {
B
bellard 已提交
2193
        /* I/O case */
2194
        addr = memory_region_section_addr(section, addr);
2195
        val = io_mem_read(section->mr, addr, 4);
2196 2197 2198 2199 2200 2201 2202 2203 2204
#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 已提交
2205 2206
    } else {
        /* RAM case */
2207
        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
2208
                                & TARGET_PAGE_MASK)
2209
                               + memory_region_section_addr(section, addr));
2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220
        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 已提交
2221 2222 2223 2224
    }
    return val;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

B
bellard 已提交
2366 2367 2368
/* 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 已提交
2369
void stl_phys_notdirty(hwaddr addr, uint32_t val)
B
bellard 已提交
2370 2371
{
    uint8_t *ptr;
2372
    MemoryRegionSection *section;
B
bellard 已提交
2373

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

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

        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 */
2394 2395
                cpu_physical_memory_set_dirty_flags(
                    addr1, (0xff & ~CODE_DIRTY_FLAG));
A
aliguori 已提交
2396 2397
            }
        }
B
bellard 已提交
2398 2399 2400
    }
}

A
Avi Kivity 已提交
2401
void stq_phys_notdirty(hwaddr addr, uint64_t val)
J
j_mayer 已提交
2402 2403
{
    uint8_t *ptr;
2404
    MemoryRegionSection *section;
J
j_mayer 已提交
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
        }
J
j_mayer 已提交
2413
#ifdef TARGET_WORDS_BIGENDIAN
2414 2415
        io_mem_write(section->mr, addr, val >> 32, 4);
        io_mem_write(section->mr, addr + 4, (uint32_t)val, 4);
J
j_mayer 已提交
2416
#else
2417 2418
        io_mem_write(section->mr, addr, (uint32_t)val, 4);
        io_mem_write(section->mr, addr + 4, val >> 32, 4);
J
j_mayer 已提交
2419 2420
#endif
    } else {
2421
        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
2422
                                & TARGET_PAGE_MASK)
2423
                               + memory_region_section_addr(section, addr));
J
j_mayer 已提交
2424 2425 2426 2427
        stq_p(ptr, val);
    }
}

B
bellard 已提交
2428
/* warning: addr must be aligned */
A
Avi Kivity 已提交
2429
static inline void stl_phys_internal(hwaddr addr, uint32_t val,
2430
                                     enum device_endian endian)
B
bellard 已提交
2431 2432
{
    uint8_t *ptr;
2433
    MemoryRegionSection *section;
B
bellard 已提交
2434

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

2437
    if (!memory_region_is_ram(section->mr) || section->readonly) {
2438
        addr = memory_region_section_addr(section, addr);
2439
        if (memory_region_is_ram(section->mr)) {
2440
            section = &phys_sections[phys_section_rom];
2441
        }
2442 2443 2444 2445 2446 2447 2448 2449 2450
#if defined(TARGET_WORDS_BIGENDIAN)
        if (endian == DEVICE_LITTLE_ENDIAN) {
            val = bswap32(val);
        }
#else
        if (endian == DEVICE_BIG_ENDIAN) {
            val = bswap32(val);
        }
#endif
2451
        io_mem_write(section->mr, addr, val, 4);
B
bellard 已提交
2452 2453
    } else {
        unsigned long addr1;
2454
        addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
2455
            + memory_region_section_addr(section, addr);
B
bellard 已提交
2456
        /* RAM case */
P
pbrook 已提交
2457
        ptr = qemu_get_ram_ptr(addr1);
2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468
        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;
        }
2469
        invalidate_and_set_dirty(addr1, 4);
B
bellard 已提交
2470 2471 2472
    }
}

A
Avi Kivity 已提交
2473
void stl_phys(hwaddr addr, uint32_t val)
2474 2475 2476 2477
{
    stl_phys_internal(addr, val, DEVICE_NATIVE_ENDIAN);
}

A
Avi Kivity 已提交
2478
void stl_le_phys(hwaddr addr, uint32_t val)
2479 2480 2481 2482
{
    stl_phys_internal(addr, val, DEVICE_LITTLE_ENDIAN);
}

A
Avi Kivity 已提交
2483
void stl_be_phys(hwaddr addr, uint32_t val)
2484 2485 2486 2487
{
    stl_phys_internal(addr, val, DEVICE_BIG_ENDIAN);
}

B
bellard 已提交
2488
/* XXX: optimize */
A
Avi Kivity 已提交
2489
void stb_phys(hwaddr addr, uint32_t val)
B
bellard 已提交
2490 2491 2492 2493 2494
{
    uint8_t v = val;
    cpu_physical_memory_write(addr, &v, 1);
}

2495
/* warning: addr must be aligned */
A
Avi Kivity 已提交
2496
static inline void stw_phys_internal(hwaddr addr, uint32_t val,
2497
                                     enum device_endian endian)
B
bellard 已提交
2498
{
2499
    uint8_t *ptr;
2500
    MemoryRegionSection *section;
2501

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

2504
    if (!memory_region_is_ram(section->mr) || section->readonly) {
2505
        addr = memory_region_section_addr(section, addr);
2506
        if (memory_region_is_ram(section->mr)) {
2507
            section = &phys_sections[phys_section_rom];
2508
        }
2509 2510 2511 2512 2513 2514 2515 2516 2517
#if defined(TARGET_WORDS_BIGENDIAN)
        if (endian == DEVICE_LITTLE_ENDIAN) {
            val = bswap16(val);
        }
#else
        if (endian == DEVICE_BIG_ENDIAN) {
            val = bswap16(val);
        }
#endif
2518
        io_mem_write(section->mr, addr, val, 2);
2519 2520
    } else {
        unsigned long addr1;
2521
        addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
2522
            + memory_region_section_addr(section, addr);
2523 2524
        /* RAM case */
        ptr = qemu_get_ram_ptr(addr1);
2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535
        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;
        }
2536
        invalidate_and_set_dirty(addr1, 2);
2537
    }
B
bellard 已提交
2538 2539
}

A
Avi Kivity 已提交
2540
void stw_phys(hwaddr addr, uint32_t val)
2541 2542 2543 2544
{
    stw_phys_internal(addr, val, DEVICE_NATIVE_ENDIAN);
}

A
Avi Kivity 已提交
2545
void stw_le_phys(hwaddr addr, uint32_t val)
2546 2547 2548 2549
{
    stw_phys_internal(addr, val, DEVICE_LITTLE_ENDIAN);
}

A
Avi Kivity 已提交
2550
void stw_be_phys(hwaddr addr, uint32_t val)
2551 2552 2553 2554
{
    stw_phys_internal(addr, val, DEVICE_BIG_ENDIAN);
}

B
bellard 已提交
2555
/* XXX: optimize */
A
Avi Kivity 已提交
2556
void stq_phys(hwaddr addr, uint64_t val)
B
bellard 已提交
2557 2558
{
    val = tswap64(val);
2559
    cpu_physical_memory_write(addr, &val, 8);
B
bellard 已提交
2560 2561
}

A
Avi Kivity 已提交
2562
void stq_le_phys(hwaddr addr, uint64_t val)
2563 2564 2565 2566 2567
{
    val = cpu_to_le64(val);
    cpu_physical_memory_write(addr, &val, 8);
}

A
Avi Kivity 已提交
2568
void stq_be_phys(hwaddr addr, uint64_t val)
2569 2570 2571 2572 2573
{
    val = cpu_to_be64(val);
    cpu_physical_memory_write(addr, &val, 8);
}

2574
/* virtual memory access for debug (includes writing to ROM) */
2575
int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
2576
                        uint8_t *buf, int len, int is_write)
B
bellard 已提交
2577 2578
{
    int l;
A
Avi Kivity 已提交
2579
    hwaddr phys_addr;
2580
    target_ulong page;
B
bellard 已提交
2581 2582 2583 2584 2585 2586 2587 2588 2589 2590

    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;
2591 2592 2593 2594 2595
        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 已提交
2596 2597 2598 2599 2600 2601
        len -= l;
        buf += l;
        addr += l;
    }
    return 0;
}
P
Paul Brook 已提交
2602
#endif
B
bellard 已提交
2603

2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621
#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

2622
#ifndef CONFIG_USER_ONLY
A
Avi Kivity 已提交
2623
bool cpu_physical_memory_is_io(hwaddr phys_addr)
2624 2625 2626
{
    MemoryRegionSection *section;

A
Avi Kivity 已提交
2627 2628
    section = phys_page_find(address_space_memory.dispatch,
                             phys_addr >> TARGET_PAGE_BITS);
2629 2630 2631 2632 2633

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