154936004Sbellard /* 25b6dd868SBlue Swirl * Virtual page mapping 354936004Sbellard * 454936004Sbellard * Copyright (c) 2003 Fabrice Bellard 554936004Sbellard * 654936004Sbellard * This library is free software; you can redistribute it and/or 754936004Sbellard * modify it under the terms of the GNU Lesser General Public 854936004Sbellard * License as published by the Free Software Foundation; either 954936004Sbellard * version 2 of the License, or (at your option) any later version. 1054936004Sbellard * 1154936004Sbellard * This library is distributed in the hope that it will be useful, 1254936004Sbellard * but WITHOUT ANY WARRANTY; without even the implied warranty of 1354936004Sbellard * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1454936004Sbellard * Lesser General Public License for more details. 1554936004Sbellard * 1654936004Sbellard * You should have received a copy of the GNU Lesser General Public 178167ee88SBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 1854936004Sbellard */ 197b31bbc2SPeter Maydell #include "qemu/osdep.h" 20da34e65cSMarkus Armbruster #include "qapi/error.h" 21777872e5SStefan Weil #ifndef _WIN32 22d5a8f07cSbellard #endif 2354936004Sbellard 24f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 256180a181Sbellard #include "cpu.h" 2663c91552SPaolo Bonzini #include "exec/exec-all.h" 2751180423SJuan Quintela #include "exec/target_page.h" 28b67d9a52Sbellard #include "tcg.h" 29741da0d3SPaolo Bonzini #include "hw/qdev-core.h" 304485bd26SMichael S. Tsirkin #if !defined(CONFIG_USER_ONLY) 3147c8ca53SMarcel Apfelbaum #include "hw/boards.h" 3233c11879SPaolo Bonzini #include "hw/xen/xen.h" 334485bd26SMichael S. Tsirkin #endif 349c17d615SPaolo Bonzini #include "sysemu/kvm.h" 352ff3de68SMarkus Armbruster #include "sysemu/sysemu.h" 361de7afc9SPaolo Bonzini #include "qemu/timer.h" 371de7afc9SPaolo Bonzini #include "qemu/config-file.h" 3875a34036SAndreas Färber #include "qemu/error-report.h" 3953a5960aSpbrook #if defined(CONFIG_USER_ONLY) 40a9c94277SMarkus Armbruster #include "qemu.h" 41432d268cSJun Nakajima #else /* !CONFIG_USER_ONLY */ 42741da0d3SPaolo Bonzini #include "hw/hw.h" 43741da0d3SPaolo Bonzini #include "exec/memory.h" 44df43d49cSPaolo Bonzini #include "exec/ioport.h" 45741da0d3SPaolo Bonzini #include "sysemu/dma.h" 469c607668SAlexey Kardashevskiy #include "sysemu/numa.h" 4779ca7a1bSChristian Borntraeger #include "sysemu/hw_accel.h" 48741da0d3SPaolo Bonzini #include "exec/address-spaces.h" 499c17d615SPaolo Bonzini #include "sysemu/xen-mapcache.h" 500ab8ed18SDaniel P. Berrange #include "trace-root.h" 51d3a5038cSDr. David Alan Gilbert 52e2fa71f5SDr. David Alan Gilbert #ifdef CONFIG_FALLOCATE_PUNCH_HOLE 53e2fa71f5SDr. David Alan Gilbert #include <fcntl.h> 54e2fa71f5SDr. David Alan Gilbert #include <linux/falloc.h> 55e2fa71f5SDr. David Alan Gilbert #endif 56e2fa71f5SDr. David Alan Gilbert 5753a5960aSpbrook #endif 580d6d3c87SPaolo Bonzini #include "exec/cpu-all.h" 590dc3f44aSMike Day #include "qemu/rcu_queue.h" 604840f10eSJan Kiszka #include "qemu/main-loop.h" 615b6dd868SBlue Swirl #include "translate-all.h" 627615936eSPavel Dovgalyuk #include "sysemu/replay.h" 630cac1b66SBlue Swirl 64022c62cbSPaolo Bonzini #include "exec/memory-internal.h" 65220c3ebdSJuan Quintela #include "exec/ram_addr.h" 66508127e2SPaolo Bonzini #include "exec/log.h" 6767d95c15SAvi Kivity 689dfeca7cSBharata B Rao #include "migration/vmstate.h" 699dfeca7cSBharata B Rao 70b35ba30fSMichael S. Tsirkin #include "qemu/range.h" 71794e8f30SMichael S. Tsirkin #ifndef _WIN32 72794e8f30SMichael S. Tsirkin #include "qemu/mmap-alloc.h" 73794e8f30SMichael S. Tsirkin #endif 74b35ba30fSMichael S. Tsirkin 75be9b23c4SPeter Xu #include "monitor/monitor.h" 76be9b23c4SPeter Xu 77db7b5426Sblueswir1 //#define DEBUG_SUBPAGE 781196be37Sths 7999773bd4Spbrook #if !defined(CONFIG_USER_ONLY) 800dc3f44aSMike Day /* ram_list is read under rcu_read_lock()/rcu_read_unlock(). Writes 810dc3f44aSMike Day * are protected by the ramlist lock. 820dc3f44aSMike Day */ 830d53d9feSMike Day RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) }; 8462152b8aSAvi Kivity 8562152b8aSAvi Kivity static MemoryRegion *system_memory; 86309cb471SAvi Kivity static MemoryRegion *system_io; 8762152b8aSAvi Kivity 88f6790af6SAvi Kivity AddressSpace address_space_io; 89f6790af6SAvi Kivity AddressSpace address_space_memory; 902673a5daSAvi Kivity 910844e007SPaolo Bonzini MemoryRegion io_mem_rom, io_mem_notdirty; 92acc9d80bSJan Kiszka static MemoryRegion io_mem_unassigned; 930e0df1e2SAvi Kivity 947bd4f430SPaolo Bonzini /* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */ 957bd4f430SPaolo Bonzini #define RAM_PREALLOC (1 << 0) 967bd4f430SPaolo Bonzini 97dbcb8981SPaolo Bonzini /* RAM is mmap-ed with MAP_SHARED */ 98dbcb8981SPaolo Bonzini #define RAM_SHARED (1 << 1) 99dbcb8981SPaolo Bonzini 10062be4e3aSMichael S. Tsirkin /* Only a portion of RAM (used_length) is actually used, and migrated. 10162be4e3aSMichael S. Tsirkin * This used_length size can change across reboots. 10262be4e3aSMichael S. Tsirkin */ 10362be4e3aSMichael S. Tsirkin #define RAM_RESIZEABLE (1 << 2) 10462be4e3aSMichael S. Tsirkin 105e2eef170Spbrook #endif 1069fa3e853Sbellard 10720bccb82SPeter Maydell #ifdef TARGET_PAGE_BITS_VARY 10820bccb82SPeter Maydell int target_page_bits; 10920bccb82SPeter Maydell bool target_page_bits_decided; 11020bccb82SPeter Maydell #endif 11120bccb82SPeter Maydell 112bdc44640SAndreas Färber struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus); 1136a00d601Sbellard /* current CPU in the current thread. It is only valid inside 1146a00d601Sbellard cpu_exec() */ 115f240eb6fSPaolo Bonzini __thread CPUState *current_cpu; 1162e70f6efSpbrook /* 0 = Do not count executed instructions. 117bf20dc07Sths 1 = Precise instruction counting. 1182e70f6efSpbrook 2 = Adaptive rate instruction counting. */ 1195708fc66SPaolo Bonzini int use_icount; 1206a00d601Sbellard 12120bccb82SPeter Maydell bool set_preferred_target_page_bits(int bits) 12220bccb82SPeter Maydell { 12320bccb82SPeter Maydell /* The target page size is the lowest common denominator for all 12420bccb82SPeter Maydell * the CPUs in the system, so we can only make it smaller, never 12520bccb82SPeter Maydell * larger. And we can't make it smaller once we've committed to 12620bccb82SPeter Maydell * a particular size. 12720bccb82SPeter Maydell */ 12820bccb82SPeter Maydell #ifdef TARGET_PAGE_BITS_VARY 12920bccb82SPeter Maydell assert(bits >= TARGET_PAGE_BITS_MIN); 13020bccb82SPeter Maydell if (target_page_bits == 0 || target_page_bits > bits) { 13120bccb82SPeter Maydell if (target_page_bits_decided) { 13220bccb82SPeter Maydell return false; 13320bccb82SPeter Maydell } 13420bccb82SPeter Maydell target_page_bits = bits; 13520bccb82SPeter Maydell } 13620bccb82SPeter Maydell #endif 13720bccb82SPeter Maydell return true; 13820bccb82SPeter Maydell } 13920bccb82SPeter Maydell 140e2eef170Spbrook #if !defined(CONFIG_USER_ONLY) 1414346ae3eSAvi Kivity 14220bccb82SPeter Maydell static void finalize_target_page_bits(void) 14320bccb82SPeter Maydell { 14420bccb82SPeter Maydell #ifdef TARGET_PAGE_BITS_VARY 14520bccb82SPeter Maydell if (target_page_bits == 0) { 14620bccb82SPeter Maydell target_page_bits = TARGET_PAGE_BITS_MIN; 14720bccb82SPeter Maydell } 14820bccb82SPeter Maydell target_page_bits_decided = true; 14920bccb82SPeter Maydell #endif 15020bccb82SPeter Maydell } 15120bccb82SPeter Maydell 1521db8abb1SPaolo Bonzini typedef struct PhysPageEntry PhysPageEntry; 1531db8abb1SPaolo Bonzini 1541db8abb1SPaolo Bonzini struct PhysPageEntry { 1559736e55bSMichael S. Tsirkin /* How many bits skip to next level (in units of L2_SIZE). 0 for a leaf. */ 1568b795765SMichael S. Tsirkin uint32_t skip : 6; 1579736e55bSMichael S. Tsirkin /* index into phys_sections (!skip) or phys_map_nodes (skip) */ 1588b795765SMichael S. Tsirkin uint32_t ptr : 26; 1591db8abb1SPaolo Bonzini }; 1601db8abb1SPaolo Bonzini 1618b795765SMichael S. Tsirkin #define PHYS_MAP_NODE_NIL (((uint32_t)~0) >> 6) 1628b795765SMichael S. Tsirkin 16303f49957SPaolo Bonzini /* Size of the L2 (and L3, etc) page tables. */ 16457271d63SPaolo Bonzini #define ADDR_SPACE_BITS 64 16503f49957SPaolo Bonzini 166026736ceSMichael S. Tsirkin #define P_L2_BITS 9 16703f49957SPaolo Bonzini #define P_L2_SIZE (1 << P_L2_BITS) 16803f49957SPaolo Bonzini 16903f49957SPaolo Bonzini #define P_L2_LEVELS (((ADDR_SPACE_BITS - TARGET_PAGE_BITS - 1) / P_L2_BITS) + 1) 17003f49957SPaolo Bonzini 17103f49957SPaolo Bonzini typedef PhysPageEntry Node[P_L2_SIZE]; 1720475d94fSPaolo Bonzini 17353cb28cbSMarcel Apfelbaum typedef struct PhysPageMap { 17479e2b9aeSPaolo Bonzini struct rcu_head rcu; 17579e2b9aeSPaolo Bonzini 17653cb28cbSMarcel Apfelbaum unsigned sections_nb; 17753cb28cbSMarcel Apfelbaum unsigned sections_nb_alloc; 17853cb28cbSMarcel Apfelbaum unsigned nodes_nb; 17953cb28cbSMarcel Apfelbaum unsigned nodes_nb_alloc; 18053cb28cbSMarcel Apfelbaum Node *nodes; 18153cb28cbSMarcel Apfelbaum MemoryRegionSection *sections; 18253cb28cbSMarcel Apfelbaum } PhysPageMap; 18353cb28cbSMarcel Apfelbaum 1841db8abb1SPaolo Bonzini struct AddressSpaceDispatch { 18579e2b9aeSPaolo Bonzini struct rcu_head rcu; 18679e2b9aeSPaolo Bonzini 187729633c2SFam Zheng MemoryRegionSection *mru_section; 1881db8abb1SPaolo Bonzini /* This is a multi-level map on the physical address space. 1891db8abb1SPaolo Bonzini * The bottom level has pointers to MemoryRegionSections. 1901db8abb1SPaolo Bonzini */ 1911db8abb1SPaolo Bonzini PhysPageEntry phys_map; 19253cb28cbSMarcel Apfelbaum PhysPageMap map; 193acc9d80bSJan Kiszka AddressSpace *as; 1941db8abb1SPaolo Bonzini }; 1951db8abb1SPaolo Bonzini 19690260c6cSJan Kiszka #define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK) 19790260c6cSJan Kiszka typedef struct subpage_t { 19890260c6cSJan Kiszka MemoryRegion iomem; 199acc9d80bSJan Kiszka AddressSpace *as; 20090260c6cSJan Kiszka hwaddr base; 2012615fabdSVijaya Kumar K uint16_t sub_section[]; 20290260c6cSJan Kiszka } subpage_t; 20390260c6cSJan Kiszka 204b41aac4fSLiu Ping Fan #define PHYS_SECTION_UNASSIGNED 0 205b41aac4fSLiu Ping Fan #define PHYS_SECTION_NOTDIRTY 1 206b41aac4fSLiu Ping Fan #define PHYS_SECTION_ROM 2 207b41aac4fSLiu Ping Fan #define PHYS_SECTION_WATCH 3 2085312bd8bSAvi Kivity 209e2eef170Spbrook static void io_mem_init(void); 21062152b8aSAvi Kivity static void memory_map_init(void); 21109daed84SEdgar E. Iglesias static void tcg_commit(MemoryListener *listener); 212e2eef170Spbrook 2131ec9b909SAvi Kivity static MemoryRegion io_mem_watch; 21432857f4dSPeter Maydell 21532857f4dSPeter Maydell /** 21632857f4dSPeter Maydell * CPUAddressSpace: all the information a CPU needs about an AddressSpace 21732857f4dSPeter Maydell * @cpu: the CPU whose AddressSpace this is 21832857f4dSPeter Maydell * @as: the AddressSpace itself 21932857f4dSPeter Maydell * @memory_dispatch: its dispatch pointer (cached, RCU protected) 22032857f4dSPeter Maydell * @tcg_as_listener: listener for tracking changes to the AddressSpace 22132857f4dSPeter Maydell */ 22232857f4dSPeter Maydell struct CPUAddressSpace { 22332857f4dSPeter Maydell CPUState *cpu; 22432857f4dSPeter Maydell AddressSpace *as; 22532857f4dSPeter Maydell struct AddressSpaceDispatch *memory_dispatch; 22632857f4dSPeter Maydell MemoryListener tcg_as_listener; 22732857f4dSPeter Maydell }; 22832857f4dSPeter Maydell 2298deaf12cSGerd Hoffmann struct DirtyBitmapSnapshot { 2308deaf12cSGerd Hoffmann ram_addr_t start; 2318deaf12cSGerd Hoffmann ram_addr_t end; 2328deaf12cSGerd Hoffmann unsigned long dirty[]; 2338deaf12cSGerd Hoffmann }; 2348deaf12cSGerd Hoffmann 2356658ffb8Spbrook #endif 23654936004Sbellard 2376d9a1304SPaul Brook #if !defined(CONFIG_USER_ONLY) 238d6f2ea22SAvi Kivity 23953cb28cbSMarcel Apfelbaum static void phys_map_node_reserve(PhysPageMap *map, unsigned nodes) 240f7bf5461SAvi Kivity { 241101420b8SPeter Lieven static unsigned alloc_hint = 16; 24253cb28cbSMarcel Apfelbaum if (map->nodes_nb + nodes > map->nodes_nb_alloc) { 243101420b8SPeter Lieven map->nodes_nb_alloc = MAX(map->nodes_nb_alloc, alloc_hint); 24453cb28cbSMarcel Apfelbaum map->nodes_nb_alloc = MAX(map->nodes_nb_alloc, map->nodes_nb + nodes); 24553cb28cbSMarcel Apfelbaum map->nodes = g_renew(Node, map->nodes, map->nodes_nb_alloc); 246101420b8SPeter Lieven alloc_hint = map->nodes_nb_alloc; 247f7bf5461SAvi Kivity } 248f7bf5461SAvi Kivity } 249f7bf5461SAvi Kivity 250db94604bSPaolo Bonzini static uint32_t phys_map_node_alloc(PhysPageMap *map, bool leaf) 251d6f2ea22SAvi Kivity { 252d6f2ea22SAvi Kivity unsigned i; 2538b795765SMichael S. Tsirkin uint32_t ret; 254db94604bSPaolo Bonzini PhysPageEntry e; 255db94604bSPaolo Bonzini PhysPageEntry *p; 256d6f2ea22SAvi Kivity 25753cb28cbSMarcel Apfelbaum ret = map->nodes_nb++; 258db94604bSPaolo Bonzini p = map->nodes[ret]; 259d6f2ea22SAvi Kivity assert(ret != PHYS_MAP_NODE_NIL); 26053cb28cbSMarcel Apfelbaum assert(ret != map->nodes_nb_alloc); 261db94604bSPaolo Bonzini 262db94604bSPaolo Bonzini e.skip = leaf ? 0 : 1; 263db94604bSPaolo Bonzini e.ptr = leaf ? PHYS_SECTION_UNASSIGNED : PHYS_MAP_NODE_NIL; 26403f49957SPaolo Bonzini for (i = 0; i < P_L2_SIZE; ++i) { 265db94604bSPaolo Bonzini memcpy(&p[i], &e, sizeof(e)); 266d6f2ea22SAvi Kivity } 267f7bf5461SAvi Kivity return ret; 268d6f2ea22SAvi Kivity } 269d6f2ea22SAvi Kivity 27053cb28cbSMarcel Apfelbaum static void phys_page_set_level(PhysPageMap *map, PhysPageEntry *lp, 27153cb28cbSMarcel Apfelbaum hwaddr *index, hwaddr *nb, uint16_t leaf, 2722999097bSAvi Kivity int level) 27392e873b9Sbellard { 274f7bf5461SAvi Kivity PhysPageEntry *p; 27503f49957SPaolo Bonzini hwaddr step = (hwaddr)1 << (level * P_L2_BITS); 2765cd2c5b6SRichard Henderson 2779736e55bSMichael S. Tsirkin if (lp->skip && lp->ptr == PHYS_MAP_NODE_NIL) { 278db94604bSPaolo Bonzini lp->ptr = phys_map_node_alloc(map, level == 0); 279db94604bSPaolo Bonzini } 28053cb28cbSMarcel Apfelbaum p = map->nodes[lp->ptr]; 28103f49957SPaolo Bonzini lp = &p[(*index >> (level * P_L2_BITS)) & (P_L2_SIZE - 1)]; 282f7bf5461SAvi Kivity 28303f49957SPaolo Bonzini while (*nb && lp < &p[P_L2_SIZE]) { 28407f07b31SAvi Kivity if ((*index & (step - 1)) == 0 && *nb >= step) { 2859736e55bSMichael S. Tsirkin lp->skip = 0; 286c19e8800SAvi Kivity lp->ptr = leaf; 28707f07b31SAvi Kivity *index += step; 28807f07b31SAvi Kivity *nb -= step; 289f7bf5461SAvi Kivity } else { 29053cb28cbSMarcel Apfelbaum phys_page_set_level(map, lp, index, nb, leaf, level - 1); 2912999097bSAvi Kivity } 2922999097bSAvi Kivity ++lp; 293f7bf5461SAvi Kivity } 2944346ae3eSAvi Kivity } 2955cd2c5b6SRichard Henderson 296ac1970fbSAvi Kivity static void phys_page_set(AddressSpaceDispatch *d, 297a8170e5eSAvi Kivity hwaddr index, hwaddr nb, 2982999097bSAvi Kivity uint16_t leaf) 299f7bf5461SAvi Kivity { 3002999097bSAvi Kivity /* Wildly overreserve - it doesn't matter much. */ 30153cb28cbSMarcel Apfelbaum phys_map_node_reserve(&d->map, 3 * P_L2_LEVELS); 302f7bf5461SAvi Kivity 30353cb28cbSMarcel Apfelbaum phys_page_set_level(&d->map, &d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1); 30492e873b9Sbellard } 30592e873b9Sbellard 306b35ba30fSMichael S. Tsirkin /* Compact a non leaf page entry. Simply detect that the entry has a single child, 307b35ba30fSMichael S. Tsirkin * and update our entry so we can skip it and go directly to the destination. 308b35ba30fSMichael S. Tsirkin */ 309efee678dSMarc-André Lureau static void phys_page_compact(PhysPageEntry *lp, Node *nodes) 310b35ba30fSMichael S. Tsirkin { 311b35ba30fSMichael S. Tsirkin unsigned valid_ptr = P_L2_SIZE; 312b35ba30fSMichael S. Tsirkin int valid = 0; 313b35ba30fSMichael S. Tsirkin PhysPageEntry *p; 314b35ba30fSMichael S. Tsirkin int i; 315b35ba30fSMichael S. Tsirkin 316b35ba30fSMichael S. Tsirkin if (lp->ptr == PHYS_MAP_NODE_NIL) { 317b35ba30fSMichael S. Tsirkin return; 318b35ba30fSMichael S. Tsirkin } 319b35ba30fSMichael S. Tsirkin 320b35ba30fSMichael S. Tsirkin p = nodes[lp->ptr]; 321b35ba30fSMichael S. Tsirkin for (i = 0; i < P_L2_SIZE; i++) { 322b35ba30fSMichael S. Tsirkin if (p[i].ptr == PHYS_MAP_NODE_NIL) { 323b35ba30fSMichael S. Tsirkin continue; 324b35ba30fSMichael S. Tsirkin } 325b35ba30fSMichael S. Tsirkin 326b35ba30fSMichael S. Tsirkin valid_ptr = i; 327b35ba30fSMichael S. Tsirkin valid++; 328b35ba30fSMichael S. Tsirkin if (p[i].skip) { 329efee678dSMarc-André Lureau phys_page_compact(&p[i], nodes); 330b35ba30fSMichael S. Tsirkin } 331b35ba30fSMichael S. Tsirkin } 332b35ba30fSMichael S. Tsirkin 333b35ba30fSMichael S. Tsirkin /* We can only compress if there's only one child. */ 334b35ba30fSMichael S. Tsirkin if (valid != 1) { 335b35ba30fSMichael S. Tsirkin return; 336b35ba30fSMichael S. Tsirkin } 337b35ba30fSMichael S. Tsirkin 338b35ba30fSMichael S. Tsirkin assert(valid_ptr < P_L2_SIZE); 339b35ba30fSMichael S. Tsirkin 340b35ba30fSMichael S. Tsirkin /* Don't compress if it won't fit in the # of bits we have. */ 341b35ba30fSMichael S. Tsirkin if (lp->skip + p[valid_ptr].skip >= (1 << 3)) { 342b35ba30fSMichael S. Tsirkin return; 343b35ba30fSMichael S. Tsirkin } 344b35ba30fSMichael S. Tsirkin 345b35ba30fSMichael S. Tsirkin lp->ptr = p[valid_ptr].ptr; 346b35ba30fSMichael S. Tsirkin if (!p[valid_ptr].skip) { 347b35ba30fSMichael S. Tsirkin /* If our only child is a leaf, make this a leaf. */ 348b35ba30fSMichael S. Tsirkin /* By design, we should have made this node a leaf to begin with so we 349b35ba30fSMichael S. Tsirkin * should never reach here. 350b35ba30fSMichael S. Tsirkin * But since it's so simple to handle this, let's do it just in case we 351b35ba30fSMichael S. Tsirkin * change this rule. 352b35ba30fSMichael S. Tsirkin */ 353b35ba30fSMichael S. Tsirkin lp->skip = 0; 354b35ba30fSMichael S. Tsirkin } else { 355b35ba30fSMichael S. Tsirkin lp->skip += p[valid_ptr].skip; 356b35ba30fSMichael S. Tsirkin } 357b35ba30fSMichael S. Tsirkin } 358b35ba30fSMichael S. Tsirkin 359b35ba30fSMichael S. Tsirkin static void phys_page_compact_all(AddressSpaceDispatch *d, int nodes_nb) 360b35ba30fSMichael S. Tsirkin { 361b35ba30fSMichael S. Tsirkin if (d->phys_map.skip) { 362efee678dSMarc-André Lureau phys_page_compact(&d->phys_map, d->map.nodes); 363b35ba30fSMichael S. Tsirkin } 364b35ba30fSMichael S. Tsirkin } 365b35ba30fSMichael S. Tsirkin 36629cb533dSFam Zheng static inline bool section_covers_addr(const MemoryRegionSection *section, 36729cb533dSFam Zheng hwaddr addr) 36829cb533dSFam Zheng { 36929cb533dSFam Zheng /* Memory topology clips a memory region to [0, 2^64); size.hi > 0 means 37029cb533dSFam Zheng * the section must cover the entire address space. 37129cb533dSFam Zheng */ 372258dfaaaSRichard Henderson return int128_gethi(section->size) || 37329cb533dSFam Zheng range_covers_byte(section->offset_within_address_space, 374258dfaaaSRichard Henderson int128_getlo(section->size), addr); 37529cb533dSFam Zheng } 37629cb533dSFam Zheng 37797115a8dSMichael S. Tsirkin static MemoryRegionSection *phys_page_find(PhysPageEntry lp, hwaddr addr, 3789affd6fcSPaolo Bonzini Node *nodes, MemoryRegionSection *sections) 37992e873b9Sbellard { 38031ab2b4aSAvi Kivity PhysPageEntry *p; 38197115a8dSMichael S. Tsirkin hwaddr index = addr >> TARGET_PAGE_BITS; 38231ab2b4aSAvi Kivity int i; 383f1f6e3b8SAvi Kivity 3849736e55bSMichael S. Tsirkin for (i = P_L2_LEVELS; lp.skip && (i -= lp.skip) >= 0;) { 385c19e8800SAvi Kivity if (lp.ptr == PHYS_MAP_NODE_NIL) { 3869affd6fcSPaolo Bonzini return §ions[PHYS_SECTION_UNASSIGNED]; 387f1f6e3b8SAvi Kivity } 3889affd6fcSPaolo Bonzini p = nodes[lp.ptr]; 38903f49957SPaolo Bonzini lp = p[(index >> (i * P_L2_BITS)) & (P_L2_SIZE - 1)]; 39031ab2b4aSAvi Kivity } 391b35ba30fSMichael S. Tsirkin 39229cb533dSFam Zheng if (section_covers_addr(§ions[lp.ptr], addr)) { 3939affd6fcSPaolo Bonzini return §ions[lp.ptr]; 394b35ba30fSMichael S. Tsirkin } else { 395b35ba30fSMichael S. Tsirkin return §ions[PHYS_SECTION_UNASSIGNED]; 396b35ba30fSMichael S. Tsirkin } 397f3705d53SAvi Kivity } 398f3705d53SAvi Kivity 399e5548617SBlue Swirl bool memory_region_is_unassigned(MemoryRegion *mr) 400e5548617SBlue Swirl { 4012a8e7499SPaolo Bonzini return mr != &io_mem_rom && mr != &io_mem_notdirty && !mr->rom_device 402e5548617SBlue Swirl && mr != &io_mem_watch; 403e5548617SBlue Swirl } 404149f54b5SPaolo Bonzini 40579e2b9aeSPaolo Bonzini /* Called from RCU critical section */ 406c7086b4aSPaolo Bonzini static MemoryRegionSection *address_space_lookup_region(AddressSpaceDispatch *d, 40790260c6cSJan Kiszka hwaddr addr, 40890260c6cSJan Kiszka bool resolve_subpage) 4099f029603SJan Kiszka { 410729633c2SFam Zheng MemoryRegionSection *section = atomic_read(&d->mru_section); 41190260c6cSJan Kiszka subpage_t *subpage; 412729633c2SFam Zheng bool update; 41390260c6cSJan Kiszka 414729633c2SFam Zheng if (section && section != &d->map.sections[PHYS_SECTION_UNASSIGNED] && 415729633c2SFam Zheng section_covers_addr(section, addr)) { 416729633c2SFam Zheng update = false; 417729633c2SFam Zheng } else { 418729633c2SFam Zheng section = phys_page_find(d->phys_map, addr, d->map.nodes, 419729633c2SFam Zheng d->map.sections); 420729633c2SFam Zheng update = true; 421729633c2SFam Zheng } 42290260c6cSJan Kiszka if (resolve_subpage && section->mr->subpage) { 42390260c6cSJan Kiszka subpage = container_of(section->mr, subpage_t, iomem); 42453cb28cbSMarcel Apfelbaum section = &d->map.sections[subpage->sub_section[SUBPAGE_IDX(addr)]]; 42590260c6cSJan Kiszka } 426729633c2SFam Zheng if (update) { 427729633c2SFam Zheng atomic_set(&d->mru_section, section); 428729633c2SFam Zheng } 42990260c6cSJan Kiszka return section; 4309f029603SJan Kiszka } 4319f029603SJan Kiszka 43279e2b9aeSPaolo Bonzini /* Called from RCU critical section */ 43390260c6cSJan Kiszka static MemoryRegionSection * 434c7086b4aSPaolo Bonzini address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *xlat, 43590260c6cSJan Kiszka hwaddr *plen, bool resolve_subpage) 436149f54b5SPaolo Bonzini { 437149f54b5SPaolo Bonzini MemoryRegionSection *section; 438965eb2fcSPaolo Bonzini MemoryRegion *mr; 439a87f3954SPaolo Bonzini Int128 diff; 440149f54b5SPaolo Bonzini 441c7086b4aSPaolo Bonzini section = address_space_lookup_region(d, addr, resolve_subpage); 442149f54b5SPaolo Bonzini /* Compute offset within MemoryRegionSection */ 443149f54b5SPaolo Bonzini addr -= section->offset_within_address_space; 444149f54b5SPaolo Bonzini 445149f54b5SPaolo Bonzini /* Compute offset within MemoryRegion */ 446149f54b5SPaolo Bonzini *xlat = addr + section->offset_within_region; 447149f54b5SPaolo Bonzini 448965eb2fcSPaolo Bonzini mr = section->mr; 449b242e0e0SPaolo Bonzini 450b242e0e0SPaolo Bonzini /* MMIO registers can be expected to perform full-width accesses based only 451b242e0e0SPaolo Bonzini * on their address, without considering adjacent registers that could 452b242e0e0SPaolo Bonzini * decode to completely different MemoryRegions. When such registers 453b242e0e0SPaolo Bonzini * exist (e.g. I/O ports 0xcf8 and 0xcf9 on most PC chipsets), MMIO 454b242e0e0SPaolo Bonzini * regions overlap wildly. For this reason we cannot clamp the accesses 455b242e0e0SPaolo Bonzini * here. 456b242e0e0SPaolo Bonzini * 457b242e0e0SPaolo Bonzini * If the length is small (as is the case for address_space_ldl/stl), 458b242e0e0SPaolo Bonzini * everything works fine. If the incoming length is large, however, 459b242e0e0SPaolo Bonzini * the caller really has to do the clamping through memory_access_size. 460b242e0e0SPaolo Bonzini */ 461965eb2fcSPaolo Bonzini if (memory_region_is_ram(mr)) { 462e4a511f8SPaolo Bonzini diff = int128_sub(section->size, int128_make64(addr)); 4633752a036SPeter Maydell *plen = int128_get64(int128_min(diff, int128_make64(*plen))); 464965eb2fcSPaolo Bonzini } 465149f54b5SPaolo Bonzini return section; 466149f54b5SPaolo Bonzini } 46790260c6cSJan Kiszka 46841063e1eSPaolo Bonzini /* Called from RCU critical section */ 469a764040cSPeter Xu static MemoryRegionSection address_space_do_translate(AddressSpace *as, 470a764040cSPeter Xu hwaddr addr, 471a764040cSPeter Xu hwaddr *xlat, 472a764040cSPeter Xu hwaddr *plen, 473a764040cSPeter Xu bool is_write, 474a764040cSPeter Xu bool is_mmio) 47590260c6cSJan Kiszka { 47630951157SAvi Kivity IOMMUTLBEntry iotlb; 47730951157SAvi Kivity MemoryRegionSection *section; 47830951157SAvi Kivity MemoryRegion *mr; 47930951157SAvi Kivity 48030951157SAvi Kivity for (;;) { 48179e2b9aeSPaolo Bonzini AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch); 482a764040cSPeter Xu section = address_space_translate_internal(d, addr, &addr, plen, is_mmio); 48330951157SAvi Kivity mr = section->mr; 48430951157SAvi Kivity 48530951157SAvi Kivity if (!mr->iommu_ops) { 48630951157SAvi Kivity break; 48730951157SAvi Kivity } 48830951157SAvi Kivity 4898d7b8cb9SLe Tan iotlb = mr->iommu_ops->translate(mr, addr, is_write); 49030951157SAvi Kivity addr = ((iotlb.translated_addr & ~iotlb.addr_mask) 49130951157SAvi Kivity | (addr & iotlb.addr_mask)); 49223820dbfSPeter Crosthwaite *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1); 49330951157SAvi Kivity if (!(iotlb.perm & (1 << is_write))) { 494a764040cSPeter Xu goto translate_fail; 49530951157SAvi Kivity } 49630951157SAvi Kivity 49730951157SAvi Kivity as = iotlb.target_as; 49830951157SAvi Kivity } 49930951157SAvi Kivity 500a764040cSPeter Xu *xlat = addr; 501a764040cSPeter Xu 502a764040cSPeter Xu return *section; 503a764040cSPeter Xu 504a764040cSPeter Xu translate_fail: 505a764040cSPeter Xu return (MemoryRegionSection) { .mr = &io_mem_unassigned }; 506a764040cSPeter Xu } 507a764040cSPeter Xu 508a764040cSPeter Xu /* Called from RCU critical section */ 509a764040cSPeter Xu IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr, 510a764040cSPeter Xu bool is_write) 511a764040cSPeter Xu { 512a764040cSPeter Xu MemoryRegionSection section; 513a764040cSPeter Xu hwaddr xlat, plen; 514a764040cSPeter Xu 515a764040cSPeter Xu /* Try to get maximum page mask during translation. */ 516a764040cSPeter Xu plen = (hwaddr)-1; 517a764040cSPeter Xu 518a764040cSPeter Xu /* This can never be MMIO. */ 519a764040cSPeter Xu section = address_space_do_translate(as, addr, &xlat, &plen, 520a764040cSPeter Xu is_write, false); 521a764040cSPeter Xu 522a764040cSPeter Xu /* Illegal translation */ 523a764040cSPeter Xu if (section.mr == &io_mem_unassigned) { 524a764040cSPeter Xu goto iotlb_fail; 525a764040cSPeter Xu } 526a764040cSPeter Xu 527a764040cSPeter Xu /* Convert memory region offset into address space offset */ 528a764040cSPeter Xu xlat += section.offset_within_address_space - 529a764040cSPeter Xu section.offset_within_region; 530a764040cSPeter Xu 531a764040cSPeter Xu if (plen == (hwaddr)-1) { 532a764040cSPeter Xu /* 533a764040cSPeter Xu * We use default page size here. Logically it only happens 534a764040cSPeter Xu * for identity mappings. 535a764040cSPeter Xu */ 536a764040cSPeter Xu plen = TARGET_PAGE_SIZE; 537a764040cSPeter Xu } 538a764040cSPeter Xu 539a764040cSPeter Xu /* Convert to address mask */ 540a764040cSPeter Xu plen -= 1; 541a764040cSPeter Xu 542a764040cSPeter Xu return (IOMMUTLBEntry) { 543a764040cSPeter Xu .target_as = section.address_space, 544a764040cSPeter Xu .iova = addr & ~plen, 545a764040cSPeter Xu .translated_addr = xlat & ~plen, 546a764040cSPeter Xu .addr_mask = plen, 547a764040cSPeter Xu /* IOTLBs are for DMAs, and DMA only allows on RAMs. */ 548a764040cSPeter Xu .perm = IOMMU_RW, 549a764040cSPeter Xu }; 550a764040cSPeter Xu 551a764040cSPeter Xu iotlb_fail: 552a764040cSPeter Xu return (IOMMUTLBEntry) {0}; 553a764040cSPeter Xu } 554a764040cSPeter Xu 555a764040cSPeter Xu /* Called from RCU critical section */ 556a764040cSPeter Xu MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, 557a764040cSPeter Xu hwaddr *xlat, hwaddr *plen, 558a764040cSPeter Xu bool is_write) 559a764040cSPeter Xu { 560a764040cSPeter Xu MemoryRegion *mr; 561a764040cSPeter Xu MemoryRegionSection section; 562a764040cSPeter Xu 563a764040cSPeter Xu /* This can be MMIO, so setup MMIO bit. */ 564a764040cSPeter Xu section = address_space_do_translate(as, addr, xlat, plen, is_write, true); 565a764040cSPeter Xu mr = section.mr; 566a764040cSPeter Xu 567fe680d0dSAlexey Kardashevskiy if (xen_enabled() && memory_access_is_direct(mr, is_write)) { 568a87f3954SPaolo Bonzini hwaddr page = ((addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE) - addr; 56923820dbfSPeter Crosthwaite *plen = MIN(page, *plen); 570a87f3954SPaolo Bonzini } 571a87f3954SPaolo Bonzini 57230951157SAvi Kivity return mr; 57390260c6cSJan Kiszka } 57490260c6cSJan Kiszka 57579e2b9aeSPaolo Bonzini /* Called from RCU critical section */ 57690260c6cSJan Kiszka MemoryRegionSection * 577d7898cdaSPeter Maydell address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr, 5789d82b5a7SPaolo Bonzini hwaddr *xlat, hwaddr *plen) 57990260c6cSJan Kiszka { 58030951157SAvi Kivity MemoryRegionSection *section; 581f35e44e7SAlex Bennée AddressSpaceDispatch *d = atomic_rcu_read(&cpu->cpu_ases[asidx].memory_dispatch); 582d7898cdaSPeter Maydell 583d7898cdaSPeter Maydell section = address_space_translate_internal(d, addr, xlat, plen, false); 58430951157SAvi Kivity 58530951157SAvi Kivity assert(!section->mr->iommu_ops); 58630951157SAvi Kivity return section; 58790260c6cSJan Kiszka } 5889fa3e853Sbellard #endif 589fd6ce8f6Sbellard 590b170fce3SAndreas Färber #if !defined(CONFIG_USER_ONLY) 5919656f324Spbrook 592e59fb374SJuan Quintela static int cpu_common_post_load(void *opaque, int version_id) 593e7f4eff7SJuan Quintela { 594259186a7SAndreas Färber CPUState *cpu = opaque; 595e7f4eff7SJuan Quintela 5963098dba0Saurel32 /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the 5973098dba0Saurel32 version_id is increased. */ 598259186a7SAndreas Färber cpu->interrupt_request &= ~0x01; 599d10eb08fSAlex Bennée tlb_flush(cpu); 6009656f324Spbrook 6019656f324Spbrook return 0; 6029656f324Spbrook } 603e7f4eff7SJuan Quintela 6046c3bff0eSPavel Dovgaluk static int cpu_common_pre_load(void *opaque) 6056c3bff0eSPavel Dovgaluk { 6066c3bff0eSPavel Dovgaluk CPUState *cpu = opaque; 6076c3bff0eSPavel Dovgaluk 608adee6424SPaolo Bonzini cpu->exception_index = -1; 6096c3bff0eSPavel Dovgaluk 6106c3bff0eSPavel Dovgaluk return 0; 6116c3bff0eSPavel Dovgaluk } 6126c3bff0eSPavel Dovgaluk 6136c3bff0eSPavel Dovgaluk static bool cpu_common_exception_index_needed(void *opaque) 6146c3bff0eSPavel Dovgaluk { 6156c3bff0eSPavel Dovgaluk CPUState *cpu = opaque; 6166c3bff0eSPavel Dovgaluk 617adee6424SPaolo Bonzini return tcg_enabled() && cpu->exception_index != -1; 6186c3bff0eSPavel Dovgaluk } 6196c3bff0eSPavel Dovgaluk 6206c3bff0eSPavel Dovgaluk static const VMStateDescription vmstate_cpu_common_exception_index = { 6216c3bff0eSPavel Dovgaluk .name = "cpu_common/exception_index", 6226c3bff0eSPavel Dovgaluk .version_id = 1, 6236c3bff0eSPavel Dovgaluk .minimum_version_id = 1, 6245cd8cadaSJuan Quintela .needed = cpu_common_exception_index_needed, 6256c3bff0eSPavel Dovgaluk .fields = (VMStateField[]) { 6266c3bff0eSPavel Dovgaluk VMSTATE_INT32(exception_index, CPUState), 6276c3bff0eSPavel Dovgaluk VMSTATE_END_OF_LIST() 6286c3bff0eSPavel Dovgaluk } 6296c3bff0eSPavel Dovgaluk }; 6306c3bff0eSPavel Dovgaluk 631bac05aa9SAndrey Smetanin static bool cpu_common_crash_occurred_needed(void *opaque) 632bac05aa9SAndrey Smetanin { 633bac05aa9SAndrey Smetanin CPUState *cpu = opaque; 634bac05aa9SAndrey Smetanin 635bac05aa9SAndrey Smetanin return cpu->crash_occurred; 636bac05aa9SAndrey Smetanin } 637bac05aa9SAndrey Smetanin 638bac05aa9SAndrey Smetanin static const VMStateDescription vmstate_cpu_common_crash_occurred = { 639bac05aa9SAndrey Smetanin .name = "cpu_common/crash_occurred", 640bac05aa9SAndrey Smetanin .version_id = 1, 641bac05aa9SAndrey Smetanin .minimum_version_id = 1, 642bac05aa9SAndrey Smetanin .needed = cpu_common_crash_occurred_needed, 643bac05aa9SAndrey Smetanin .fields = (VMStateField[]) { 644bac05aa9SAndrey Smetanin VMSTATE_BOOL(crash_occurred, CPUState), 645bac05aa9SAndrey Smetanin VMSTATE_END_OF_LIST() 646bac05aa9SAndrey Smetanin } 647bac05aa9SAndrey Smetanin }; 648bac05aa9SAndrey Smetanin 6491a1562f5SAndreas Färber const VMStateDescription vmstate_cpu_common = { 650e7f4eff7SJuan Quintela .name = "cpu_common", 651e7f4eff7SJuan Quintela .version_id = 1, 652e7f4eff7SJuan Quintela .minimum_version_id = 1, 6536c3bff0eSPavel Dovgaluk .pre_load = cpu_common_pre_load, 654e7f4eff7SJuan Quintela .post_load = cpu_common_post_load, 655e7f4eff7SJuan Quintela .fields = (VMStateField[]) { 656259186a7SAndreas Färber VMSTATE_UINT32(halted, CPUState), 657259186a7SAndreas Färber VMSTATE_UINT32(interrupt_request, CPUState), 658e7f4eff7SJuan Quintela VMSTATE_END_OF_LIST() 6596c3bff0eSPavel Dovgaluk }, 6605cd8cadaSJuan Quintela .subsections = (const VMStateDescription*[]) { 6615cd8cadaSJuan Quintela &vmstate_cpu_common_exception_index, 662bac05aa9SAndrey Smetanin &vmstate_cpu_common_crash_occurred, 6635cd8cadaSJuan Quintela NULL 664e7f4eff7SJuan Quintela } 665e7f4eff7SJuan Quintela }; 6661a1562f5SAndreas Färber 6679656f324Spbrook #endif 6689656f324Spbrook 66938d8f5c8SAndreas Färber CPUState *qemu_get_cpu(int index) 670950f1472SGlauber Costa { 671bdc44640SAndreas Färber CPUState *cpu; 672950f1472SGlauber Costa 673bdc44640SAndreas Färber CPU_FOREACH(cpu) { 67455e5c285SAndreas Färber if (cpu->cpu_index == index) { 675bdc44640SAndreas Färber return cpu; 67655e5c285SAndreas Färber } 677950f1472SGlauber Costa } 678950f1472SGlauber Costa 679bdc44640SAndreas Färber return NULL; 680950f1472SGlauber Costa } 681950f1472SGlauber Costa 68209daed84SEdgar E. Iglesias #if !defined(CONFIG_USER_ONLY) 68356943e8cSPeter Maydell void cpu_address_space_init(CPUState *cpu, AddressSpace *as, int asidx) 68409daed84SEdgar E. Iglesias { 68512ebc9a7SPeter Maydell CPUAddressSpace *newas; 68612ebc9a7SPeter Maydell 68712ebc9a7SPeter Maydell /* Target code should have set num_ases before calling us */ 68812ebc9a7SPeter Maydell assert(asidx < cpu->num_ases); 68912ebc9a7SPeter Maydell 69056943e8cSPeter Maydell if (asidx == 0) { 69156943e8cSPeter Maydell /* address space 0 gets the convenience alias */ 69256943e8cSPeter Maydell cpu->as = as; 69356943e8cSPeter Maydell } 69456943e8cSPeter Maydell 69512ebc9a7SPeter Maydell /* KVM cannot currently support multiple address spaces. */ 69612ebc9a7SPeter Maydell assert(asidx == 0 || !kvm_enabled()); 69709daed84SEdgar E. Iglesias 69812ebc9a7SPeter Maydell if (!cpu->cpu_ases) { 69912ebc9a7SPeter Maydell cpu->cpu_ases = g_new0(CPUAddressSpace, cpu->num_ases); 70009daed84SEdgar E. Iglesias } 70132857f4dSPeter Maydell 70212ebc9a7SPeter Maydell newas = &cpu->cpu_ases[asidx]; 70312ebc9a7SPeter Maydell newas->cpu = cpu; 70412ebc9a7SPeter Maydell newas->as = as; 70556943e8cSPeter Maydell if (tcg_enabled()) { 70612ebc9a7SPeter Maydell newas->tcg_as_listener.commit = tcg_commit; 70712ebc9a7SPeter Maydell memory_listener_register(&newas->tcg_as_listener, as); 70809daed84SEdgar E. Iglesias } 70956943e8cSPeter Maydell } 710651a5bc0SPeter Maydell 711651a5bc0SPeter Maydell AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx) 712651a5bc0SPeter Maydell { 713651a5bc0SPeter Maydell /* Return the AddressSpace corresponding to the specified index */ 714651a5bc0SPeter Maydell return cpu->cpu_ases[asidx].as; 715651a5bc0SPeter Maydell } 71609daed84SEdgar E. Iglesias #endif 71709daed84SEdgar E. Iglesias 7187bbc124eSLaurent Vivier void cpu_exec_unrealizefn(CPUState *cpu) 7191c59eb39SBharata B Rao { 7209dfeca7cSBharata B Rao CPUClass *cc = CPU_GET_CLASS(cpu); 7219dfeca7cSBharata B Rao 722267f685bSPaolo Bonzini cpu_list_remove(cpu); 7239dfeca7cSBharata B Rao 7249dfeca7cSBharata B Rao if (cc->vmsd != NULL) { 7259dfeca7cSBharata B Rao vmstate_unregister(NULL, cc->vmsd, cpu); 7269dfeca7cSBharata B Rao } 7279dfeca7cSBharata B Rao if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { 7289dfeca7cSBharata B Rao vmstate_unregister(NULL, &vmstate_cpu_common, cpu); 7299dfeca7cSBharata B Rao } 7301c59eb39SBharata B Rao } 7311c59eb39SBharata B Rao 73239e329e3SLaurent Vivier void cpu_exec_initfn(CPUState *cpu) 733fd6ce8f6Sbellard { 73456943e8cSPeter Maydell cpu->as = NULL; 73512ebc9a7SPeter Maydell cpu->num_ases = 0; 73656943e8cSPeter Maydell 737291135b5SEduardo Habkost #ifndef CONFIG_USER_ONLY 738291135b5SEduardo Habkost cpu->thread_id = qemu_get_thread_id(); 7396731d864SPeter Crosthwaite 7406731d864SPeter Crosthwaite /* This is a softmmu CPU object, so create a property for it 7416731d864SPeter Crosthwaite * so users can wire up its memory. (This can't go in qom/cpu.c 7426731d864SPeter Crosthwaite * because that file is compiled only once for both user-mode 7436731d864SPeter Crosthwaite * and system builds.) The default if no link is set up is to use 7446731d864SPeter Crosthwaite * the system address space. 7456731d864SPeter Crosthwaite */ 7466731d864SPeter Crosthwaite object_property_add_link(OBJECT(cpu), "memory", TYPE_MEMORY_REGION, 7476731d864SPeter Crosthwaite (Object **)&cpu->memory, 7486731d864SPeter Crosthwaite qdev_prop_allow_set_link_before_realize, 7496731d864SPeter Crosthwaite OBJ_PROP_LINK_UNREF_ON_RELEASE, 7506731d864SPeter Crosthwaite &error_abort); 7516731d864SPeter Crosthwaite cpu->memory = system_memory; 7526731d864SPeter Crosthwaite object_ref(OBJECT(cpu->memory)); 753291135b5SEduardo Habkost #endif 75439e329e3SLaurent Vivier } 75539e329e3SLaurent Vivier 756ce5b1bbfSLaurent Vivier void cpu_exec_realizefn(CPUState *cpu, Error **errp) 75739e329e3SLaurent Vivier { 75839e329e3SLaurent Vivier CPUClass *cc ATTRIBUTE_UNUSED = CPU_GET_CLASS(cpu); 759291135b5SEduardo Habkost 760267f685bSPaolo Bonzini cpu_list_add(cpu); 7611bc7e522SIgor Mammedov 7621bc7e522SIgor Mammedov #ifndef CONFIG_USER_ONLY 763e0d47944SAndreas Färber if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { 764741da0d3SPaolo Bonzini vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu); 765e0d47944SAndreas Färber } 766b170fce3SAndreas Färber if (cc->vmsd != NULL) { 767741da0d3SPaolo Bonzini vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu); 768b170fce3SAndreas Färber } 769741da0d3SPaolo Bonzini #endif 770fd6ce8f6Sbellard } 771fd6ce8f6Sbellard 77200b941e5SAndreas Färber static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) 77394df27fdSPaul Brook { 774a9353fe8SPeter Maydell /* Flush the whole TB as this will not have race conditions 775a9353fe8SPeter Maydell * even if we don't have proper locking yet. 776a9353fe8SPeter Maydell * Ideally we would just invalidate the TBs for the 777a9353fe8SPeter Maydell * specified PC. 778a9353fe8SPeter Maydell */ 779a9353fe8SPeter Maydell tb_flush(cpu); 78094df27fdSPaul Brook } 781d720b93dSbellard 782c527ee8fSPaul Brook #if defined(CONFIG_USER_ONLY) 78375a34036SAndreas Färber void cpu_watchpoint_remove_all(CPUState *cpu, int mask) 784c527ee8fSPaul Brook 785c527ee8fSPaul Brook { 786c527ee8fSPaul Brook } 787c527ee8fSPaul Brook 7883ee887e8SPeter Maydell int cpu_watchpoint_remove(CPUState *cpu, vaddr addr, vaddr len, 7893ee887e8SPeter Maydell int flags) 7903ee887e8SPeter Maydell { 7913ee887e8SPeter Maydell return -ENOSYS; 7923ee887e8SPeter Maydell } 7933ee887e8SPeter Maydell 7943ee887e8SPeter Maydell void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint) 7953ee887e8SPeter Maydell { 7963ee887e8SPeter Maydell } 7973ee887e8SPeter Maydell 79875a34036SAndreas Färber int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, 799c527ee8fSPaul Brook int flags, CPUWatchpoint **watchpoint) 800c527ee8fSPaul Brook { 801c527ee8fSPaul Brook return -ENOSYS; 802c527ee8fSPaul Brook } 803c527ee8fSPaul Brook #else 8046658ffb8Spbrook /* Add a watchpoint. */ 80575a34036SAndreas Färber int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, 806a1d1bb31Saliguori int flags, CPUWatchpoint **watchpoint) 8076658ffb8Spbrook { 808c0ce998eSaliguori CPUWatchpoint *wp; 8096658ffb8Spbrook 81005068c0dSPeter Maydell /* forbid ranges which are empty or run off the end of the address space */ 81107e2863dSMax Filippov if (len == 0 || (addr + len - 1) < addr) { 81275a34036SAndreas Färber error_report("tried to set invalid watchpoint at %" 81375a34036SAndreas Färber VADDR_PRIx ", len=%" VADDR_PRIu, addr, len); 814b4051334Saliguori return -EINVAL; 815b4051334Saliguori } 8167267c094SAnthony Liguori wp = g_malloc(sizeof(*wp)); 8176658ffb8Spbrook 818a1d1bb31Saliguori wp->vaddr = addr; 81905068c0dSPeter Maydell wp->len = len; 820a1d1bb31Saliguori wp->flags = flags; 821a1d1bb31Saliguori 8222dc9f411Saliguori /* keep all GDB-injected watchpoints in front */ 823ff4700b0SAndreas Färber if (flags & BP_GDB) { 824ff4700b0SAndreas Färber QTAILQ_INSERT_HEAD(&cpu->watchpoints, wp, entry); 825ff4700b0SAndreas Färber } else { 826ff4700b0SAndreas Färber QTAILQ_INSERT_TAIL(&cpu->watchpoints, wp, entry); 827ff4700b0SAndreas Färber } 828a1d1bb31Saliguori 82931b030d4SAndreas Färber tlb_flush_page(cpu, addr); 830a1d1bb31Saliguori 831a1d1bb31Saliguori if (watchpoint) 832a1d1bb31Saliguori *watchpoint = wp; 833a1d1bb31Saliguori return 0; 8346658ffb8Spbrook } 8356658ffb8Spbrook 836a1d1bb31Saliguori /* Remove a specific watchpoint. */ 83775a34036SAndreas Färber int cpu_watchpoint_remove(CPUState *cpu, vaddr addr, vaddr len, 838a1d1bb31Saliguori int flags) 8396658ffb8Spbrook { 840a1d1bb31Saliguori CPUWatchpoint *wp; 8416658ffb8Spbrook 842ff4700b0SAndreas Färber QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { 84305068c0dSPeter Maydell if (addr == wp->vaddr && len == wp->len 8446e140f28Saliguori && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) { 84575a34036SAndreas Färber cpu_watchpoint_remove_by_ref(cpu, wp); 8466658ffb8Spbrook return 0; 8476658ffb8Spbrook } 8486658ffb8Spbrook } 849a1d1bb31Saliguori return -ENOENT; 8506658ffb8Spbrook } 8516658ffb8Spbrook 852a1d1bb31Saliguori /* Remove a specific watchpoint by reference. */ 85375a34036SAndreas Färber void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint) 854a1d1bb31Saliguori { 855ff4700b0SAndreas Färber QTAILQ_REMOVE(&cpu->watchpoints, watchpoint, entry); 8567d03f82fSedgar_igl 85731b030d4SAndreas Färber tlb_flush_page(cpu, watchpoint->vaddr); 858a1d1bb31Saliguori 8597267c094SAnthony Liguori g_free(watchpoint); 8607d03f82fSedgar_igl } 8617d03f82fSedgar_igl 862a1d1bb31Saliguori /* Remove all matching watchpoints. */ 86375a34036SAndreas Färber void cpu_watchpoint_remove_all(CPUState *cpu, int mask) 864a1d1bb31Saliguori { 865c0ce998eSaliguori CPUWatchpoint *wp, *next; 866a1d1bb31Saliguori 867ff4700b0SAndreas Färber QTAILQ_FOREACH_SAFE(wp, &cpu->watchpoints, entry, next) { 86875a34036SAndreas Färber if (wp->flags & mask) { 86975a34036SAndreas Färber cpu_watchpoint_remove_by_ref(cpu, wp); 87075a34036SAndreas Färber } 871a1d1bb31Saliguori } 872c0ce998eSaliguori } 87305068c0dSPeter Maydell 87405068c0dSPeter Maydell /* Return true if this watchpoint address matches the specified 87505068c0dSPeter Maydell * access (ie the address range covered by the watchpoint overlaps 87605068c0dSPeter Maydell * partially or completely with the address range covered by the 87705068c0dSPeter Maydell * access). 87805068c0dSPeter Maydell */ 87905068c0dSPeter Maydell static inline bool cpu_watchpoint_address_matches(CPUWatchpoint *wp, 88005068c0dSPeter Maydell vaddr addr, 88105068c0dSPeter Maydell vaddr len) 88205068c0dSPeter Maydell { 88305068c0dSPeter Maydell /* We know the lengths are non-zero, but a little caution is 88405068c0dSPeter Maydell * required to avoid errors in the case where the range ends 88505068c0dSPeter Maydell * exactly at the top of the address space and so addr + len 88605068c0dSPeter Maydell * wraps round to zero. 88705068c0dSPeter Maydell */ 88805068c0dSPeter Maydell vaddr wpend = wp->vaddr + wp->len - 1; 88905068c0dSPeter Maydell vaddr addrend = addr + len - 1; 89005068c0dSPeter Maydell 89105068c0dSPeter Maydell return !(addr > wpend || wp->vaddr > addrend); 89205068c0dSPeter Maydell } 89305068c0dSPeter Maydell 894c527ee8fSPaul Brook #endif 895a1d1bb31Saliguori 896a1d1bb31Saliguori /* Add a breakpoint. */ 897b3310ab3SAndreas Färber int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, 898a1d1bb31Saliguori CPUBreakpoint **breakpoint) 8994c3a88a2Sbellard { 900c0ce998eSaliguori CPUBreakpoint *bp; 9014c3a88a2Sbellard 9027267c094SAnthony Liguori bp = g_malloc(sizeof(*bp)); 9034c3a88a2Sbellard 904a1d1bb31Saliguori bp->pc = pc; 905a1d1bb31Saliguori bp->flags = flags; 906a1d1bb31Saliguori 9072dc9f411Saliguori /* keep all GDB-injected breakpoints in front */ 90800b941e5SAndreas Färber if (flags & BP_GDB) { 909f0c3c505SAndreas Färber QTAILQ_INSERT_HEAD(&cpu->breakpoints, bp, entry); 91000b941e5SAndreas Färber } else { 911f0c3c505SAndreas Färber QTAILQ_INSERT_TAIL(&cpu->breakpoints, bp, entry); 91200b941e5SAndreas Färber } 913d720b93dSbellard 914f0c3c505SAndreas Färber breakpoint_invalidate(cpu, pc); 915a1d1bb31Saliguori 91600b941e5SAndreas Färber if (breakpoint) { 917a1d1bb31Saliguori *breakpoint = bp; 91800b941e5SAndreas Färber } 9194c3a88a2Sbellard return 0; 9204c3a88a2Sbellard } 9214c3a88a2Sbellard 922a1d1bb31Saliguori /* Remove a specific breakpoint. */ 923b3310ab3SAndreas Färber int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags) 924a1d1bb31Saliguori { 925a1d1bb31Saliguori CPUBreakpoint *bp; 926a1d1bb31Saliguori 927f0c3c505SAndreas Färber QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { 928a1d1bb31Saliguori if (bp->pc == pc && bp->flags == flags) { 929b3310ab3SAndreas Färber cpu_breakpoint_remove_by_ref(cpu, bp); 930a1d1bb31Saliguori return 0; 9317d03f82fSedgar_igl } 932a1d1bb31Saliguori } 933a1d1bb31Saliguori return -ENOENT; 9347d03f82fSedgar_igl } 9357d03f82fSedgar_igl 936a1d1bb31Saliguori /* Remove a specific breakpoint by reference. */ 937b3310ab3SAndreas Färber void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint) 9384c3a88a2Sbellard { 939f0c3c505SAndreas Färber QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry); 940f0c3c505SAndreas Färber 941f0c3c505SAndreas Färber breakpoint_invalidate(cpu, breakpoint->pc); 942a1d1bb31Saliguori 9437267c094SAnthony Liguori g_free(breakpoint); 944a1d1bb31Saliguori } 945a1d1bb31Saliguori 946a1d1bb31Saliguori /* Remove all matching breakpoints. */ 947b3310ab3SAndreas Färber void cpu_breakpoint_remove_all(CPUState *cpu, int mask) 948a1d1bb31Saliguori { 949c0ce998eSaliguori CPUBreakpoint *bp, *next; 950a1d1bb31Saliguori 951f0c3c505SAndreas Färber QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) { 952b3310ab3SAndreas Färber if (bp->flags & mask) { 953b3310ab3SAndreas Färber cpu_breakpoint_remove_by_ref(cpu, bp); 954b3310ab3SAndreas Färber } 955c0ce998eSaliguori } 9564c3a88a2Sbellard } 9574c3a88a2Sbellard 958c33a346eSbellard /* enable or disable single step mode. EXCP_DEBUG is returned by the 959c33a346eSbellard CPU loop after each instruction */ 9603825b28fSAndreas Färber void cpu_single_step(CPUState *cpu, int enabled) 961c33a346eSbellard { 962ed2803daSAndreas Färber if (cpu->singlestep_enabled != enabled) { 963ed2803daSAndreas Färber cpu->singlestep_enabled = enabled; 964ed2803daSAndreas Färber if (kvm_enabled()) { 96538e478ecSStefan Weil kvm_update_guest_debug(cpu, 0); 966ed2803daSAndreas Färber } else { 967ccbb4d44SStuart Brady /* must flush all the translated code to avoid inconsistencies */ 9689fa3e853Sbellard /* XXX: only flush what is necessary */ 969bbd77c18SPeter Crosthwaite tb_flush(cpu); 970c33a346eSbellard } 971e22a25c9Saliguori } 972c33a346eSbellard } 973c33a346eSbellard 974a47dddd7SAndreas Färber void cpu_abort(CPUState *cpu, const char *fmt, ...) 9757501267eSbellard { 9767501267eSbellard va_list ap; 977493ae1f0Spbrook va_list ap2; 9787501267eSbellard 9797501267eSbellard va_start(ap, fmt); 980493ae1f0Spbrook va_copy(ap2, ap); 9817501267eSbellard fprintf(stderr, "qemu: fatal: "); 9827501267eSbellard vfprintf(stderr, fmt, ap); 9837501267eSbellard fprintf(stderr, "\n"); 984878096eeSAndreas Färber cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_FPU | CPU_DUMP_CCOP); 985013a2942SPaolo Bonzini if (qemu_log_separate()) { 9861ee73216SRichard Henderson qemu_log_lock(); 98793fcfe39Saliguori qemu_log("qemu: fatal: "); 98893fcfe39Saliguori qemu_log_vprintf(fmt, ap2); 98993fcfe39Saliguori qemu_log("\n"); 990a0762859SAndreas Färber log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP); 99131b1a7b4Saliguori qemu_log_flush(); 9921ee73216SRichard Henderson qemu_log_unlock(); 99393fcfe39Saliguori qemu_log_close(); 994924edcaeSbalrog } 995493ae1f0Spbrook va_end(ap2); 996f9373291Sj_mayer va_end(ap); 9977615936eSPavel Dovgalyuk replay_finish(); 998fd052bf6SRiku Voipio #if defined(CONFIG_USER_ONLY) 999fd052bf6SRiku Voipio { 1000fd052bf6SRiku Voipio struct sigaction act; 1001fd052bf6SRiku Voipio sigfillset(&act.sa_mask); 1002fd052bf6SRiku Voipio act.sa_handler = SIG_DFL; 1003fd052bf6SRiku Voipio sigaction(SIGABRT, &act, NULL); 1004fd052bf6SRiku Voipio } 1005fd052bf6SRiku Voipio #endif 10067501267eSbellard abort(); 10077501267eSbellard } 10087501267eSbellard 10090124311eSbellard #if !defined(CONFIG_USER_ONLY) 10100dc3f44aSMike Day /* Called from RCU critical section */ 1011041603feSPaolo Bonzini static RAMBlock *qemu_get_ram_block(ram_addr_t addr) 1012041603feSPaolo Bonzini { 1013041603feSPaolo Bonzini RAMBlock *block; 1014041603feSPaolo Bonzini 101543771539SPaolo Bonzini block = atomic_rcu_read(&ram_list.mru_block); 10169b8424d5SMichael S. Tsirkin if (block && addr - block->offset < block->max_length) { 101768851b98SPaolo Bonzini return block; 1018041603feSPaolo Bonzini } 101999e15582SPeter Xu RAMBLOCK_FOREACH(block) { 10209b8424d5SMichael S. Tsirkin if (addr - block->offset < block->max_length) { 1021041603feSPaolo Bonzini goto found; 1022041603feSPaolo Bonzini } 1023041603feSPaolo Bonzini } 1024041603feSPaolo Bonzini 1025041603feSPaolo Bonzini fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr); 1026041603feSPaolo Bonzini abort(); 1027041603feSPaolo Bonzini 1028041603feSPaolo Bonzini found: 102943771539SPaolo Bonzini /* It is safe to write mru_block outside the iothread lock. This 103043771539SPaolo Bonzini * is what happens: 103143771539SPaolo Bonzini * 103243771539SPaolo Bonzini * mru_block = xxx 103343771539SPaolo Bonzini * rcu_read_unlock() 103443771539SPaolo Bonzini * xxx removed from list 103543771539SPaolo Bonzini * rcu_read_lock() 103643771539SPaolo Bonzini * read mru_block 103743771539SPaolo Bonzini * mru_block = NULL; 103843771539SPaolo Bonzini * call_rcu(reclaim_ramblock, xxx); 103943771539SPaolo Bonzini * rcu_read_unlock() 104043771539SPaolo Bonzini * 104143771539SPaolo Bonzini * atomic_rcu_set is not needed here. The block was already published 104243771539SPaolo Bonzini * when it was placed into the list. Here we're just making an extra 104343771539SPaolo Bonzini * copy of the pointer. 104443771539SPaolo Bonzini */ 1045041603feSPaolo Bonzini ram_list.mru_block = block; 1046041603feSPaolo Bonzini return block; 1047041603feSPaolo Bonzini } 1048041603feSPaolo Bonzini 1049a2f4d5beSJuan Quintela static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t length) 10501ccde1cbSbellard { 10519a13565dSPeter Crosthwaite CPUState *cpu; 1052041603feSPaolo Bonzini ram_addr_t start1; 1053a2f4d5beSJuan Quintela RAMBlock *block; 1054a2f4d5beSJuan Quintela ram_addr_t end; 1055a2f4d5beSJuan Quintela 1056a2f4d5beSJuan Quintela end = TARGET_PAGE_ALIGN(start + length); 1057a2f4d5beSJuan Quintela start &= TARGET_PAGE_MASK; 1058f23db169Sbellard 10590dc3f44aSMike Day rcu_read_lock(); 1060041603feSPaolo Bonzini block = qemu_get_ram_block(start); 1061041603feSPaolo Bonzini assert(block == qemu_get_ram_block(end - 1)); 10621240be24SMichael S. Tsirkin start1 = (uintptr_t)ramblock_ptr(block, start - block->offset); 10639a13565dSPeter Crosthwaite CPU_FOREACH(cpu) { 10649a13565dSPeter Crosthwaite tlb_reset_dirty(cpu, start1, length); 10659a13565dSPeter Crosthwaite } 10660dc3f44aSMike Day rcu_read_unlock(); 1067d24981d3SJuan Quintela } 1068d24981d3SJuan Quintela 1069d24981d3SJuan Quintela /* Note: start and end must be within the same ram block. */ 107003eebc9eSStefan Hajnoczi bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start, 107103eebc9eSStefan Hajnoczi ram_addr_t length, 107252159192SJuan Quintela unsigned client) 1073d24981d3SJuan Quintela { 10745b82b703SStefan Hajnoczi DirtyMemoryBlocks *blocks; 107503eebc9eSStefan Hajnoczi unsigned long end, page; 10765b82b703SStefan Hajnoczi bool dirty = false; 1077d24981d3SJuan Quintela 107803eebc9eSStefan Hajnoczi if (length == 0) { 107903eebc9eSStefan Hajnoczi return false; 108003eebc9eSStefan Hajnoczi } 108103eebc9eSStefan Hajnoczi 108203eebc9eSStefan Hajnoczi end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; 108303eebc9eSStefan Hajnoczi page = start >> TARGET_PAGE_BITS; 10845b82b703SStefan Hajnoczi 10855b82b703SStefan Hajnoczi rcu_read_lock(); 10865b82b703SStefan Hajnoczi 10875b82b703SStefan Hajnoczi blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); 10885b82b703SStefan Hajnoczi 10895b82b703SStefan Hajnoczi while (page < end) { 10905b82b703SStefan Hajnoczi unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE; 10915b82b703SStefan Hajnoczi unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE; 10925b82b703SStefan Hajnoczi unsigned long num = MIN(end - page, DIRTY_MEMORY_BLOCK_SIZE - offset); 10935b82b703SStefan Hajnoczi 10945b82b703SStefan Hajnoczi dirty |= bitmap_test_and_clear_atomic(blocks->blocks[idx], 10955b82b703SStefan Hajnoczi offset, num); 10965b82b703SStefan Hajnoczi page += num; 10975b82b703SStefan Hajnoczi } 10985b82b703SStefan Hajnoczi 10995b82b703SStefan Hajnoczi rcu_read_unlock(); 110003eebc9eSStefan Hajnoczi 110103eebc9eSStefan Hajnoczi if (dirty && tcg_enabled()) { 1102a2f4d5beSJuan Quintela tlb_reset_dirty_range_all(start, length); 1103d24981d3SJuan Quintela } 110403eebc9eSStefan Hajnoczi 110503eebc9eSStefan Hajnoczi return dirty; 11061ccde1cbSbellard } 11071ccde1cbSbellard 11088deaf12cSGerd Hoffmann DirtyBitmapSnapshot *cpu_physical_memory_snapshot_and_clear_dirty 11098deaf12cSGerd Hoffmann (ram_addr_t start, ram_addr_t length, unsigned client) 11108deaf12cSGerd Hoffmann { 11118deaf12cSGerd Hoffmann DirtyMemoryBlocks *blocks; 11128deaf12cSGerd Hoffmann unsigned long align = 1UL << (TARGET_PAGE_BITS + BITS_PER_LEVEL); 11138deaf12cSGerd Hoffmann ram_addr_t first = QEMU_ALIGN_DOWN(start, align); 11148deaf12cSGerd Hoffmann ram_addr_t last = QEMU_ALIGN_UP(start + length, align); 11158deaf12cSGerd Hoffmann DirtyBitmapSnapshot *snap; 11168deaf12cSGerd Hoffmann unsigned long page, end, dest; 11178deaf12cSGerd Hoffmann 11188deaf12cSGerd Hoffmann snap = g_malloc0(sizeof(*snap) + 11198deaf12cSGerd Hoffmann ((last - first) >> (TARGET_PAGE_BITS + 3))); 11208deaf12cSGerd Hoffmann snap->start = first; 11218deaf12cSGerd Hoffmann snap->end = last; 11228deaf12cSGerd Hoffmann 11238deaf12cSGerd Hoffmann page = first >> TARGET_PAGE_BITS; 11248deaf12cSGerd Hoffmann end = last >> TARGET_PAGE_BITS; 11258deaf12cSGerd Hoffmann dest = 0; 11268deaf12cSGerd Hoffmann 11278deaf12cSGerd Hoffmann rcu_read_lock(); 11288deaf12cSGerd Hoffmann 11298deaf12cSGerd Hoffmann blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); 11308deaf12cSGerd Hoffmann 11318deaf12cSGerd Hoffmann while (page < end) { 11328deaf12cSGerd Hoffmann unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE; 11338deaf12cSGerd Hoffmann unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE; 11348deaf12cSGerd Hoffmann unsigned long num = MIN(end - page, DIRTY_MEMORY_BLOCK_SIZE - offset); 11358deaf12cSGerd Hoffmann 11368deaf12cSGerd Hoffmann assert(QEMU_IS_ALIGNED(offset, (1 << BITS_PER_LEVEL))); 11378deaf12cSGerd Hoffmann assert(QEMU_IS_ALIGNED(num, (1 << BITS_PER_LEVEL))); 11388deaf12cSGerd Hoffmann offset >>= BITS_PER_LEVEL; 11398deaf12cSGerd Hoffmann 11408deaf12cSGerd Hoffmann bitmap_copy_and_clear_atomic(snap->dirty + dest, 11418deaf12cSGerd Hoffmann blocks->blocks[idx] + offset, 11428deaf12cSGerd Hoffmann num); 11438deaf12cSGerd Hoffmann page += num; 11448deaf12cSGerd Hoffmann dest += num >> BITS_PER_LEVEL; 11458deaf12cSGerd Hoffmann } 11468deaf12cSGerd Hoffmann 11478deaf12cSGerd Hoffmann rcu_read_unlock(); 11488deaf12cSGerd Hoffmann 11498deaf12cSGerd Hoffmann if (tcg_enabled()) { 11508deaf12cSGerd Hoffmann tlb_reset_dirty_range_all(start, length); 11518deaf12cSGerd Hoffmann } 11528deaf12cSGerd Hoffmann 11538deaf12cSGerd Hoffmann return snap; 11548deaf12cSGerd Hoffmann } 11558deaf12cSGerd Hoffmann 11568deaf12cSGerd Hoffmann bool cpu_physical_memory_snapshot_get_dirty(DirtyBitmapSnapshot *snap, 11578deaf12cSGerd Hoffmann ram_addr_t start, 11588deaf12cSGerd Hoffmann ram_addr_t length) 11598deaf12cSGerd Hoffmann { 11608deaf12cSGerd Hoffmann unsigned long page, end; 11618deaf12cSGerd Hoffmann 11628deaf12cSGerd Hoffmann assert(start >= snap->start); 11638deaf12cSGerd Hoffmann assert(start + length <= snap->end); 11648deaf12cSGerd Hoffmann 11658deaf12cSGerd Hoffmann end = TARGET_PAGE_ALIGN(start + length - snap->start) >> TARGET_PAGE_BITS; 11668deaf12cSGerd Hoffmann page = (start - snap->start) >> TARGET_PAGE_BITS; 11678deaf12cSGerd Hoffmann 11688deaf12cSGerd Hoffmann while (page < end) { 11698deaf12cSGerd Hoffmann if (test_bit(page, snap->dirty)) { 11708deaf12cSGerd Hoffmann return true; 11718deaf12cSGerd Hoffmann } 11728deaf12cSGerd Hoffmann page++; 11738deaf12cSGerd Hoffmann } 11748deaf12cSGerd Hoffmann return false; 11758deaf12cSGerd Hoffmann } 11768deaf12cSGerd Hoffmann 117779e2b9aeSPaolo Bonzini /* Called from RCU critical section */ 1178bb0e627aSAndreas Färber hwaddr memory_region_section_get_iotlb(CPUState *cpu, 1179e5548617SBlue Swirl MemoryRegionSection *section, 1180e5548617SBlue Swirl target_ulong vaddr, 1181149f54b5SPaolo Bonzini hwaddr paddr, hwaddr xlat, 1182e5548617SBlue Swirl int prot, 1183e5548617SBlue Swirl target_ulong *address) 1184e5548617SBlue Swirl { 1185a8170e5eSAvi Kivity hwaddr iotlb; 1186e5548617SBlue Swirl CPUWatchpoint *wp; 1187e5548617SBlue Swirl 1188cc5bea60SBlue Swirl if (memory_region_is_ram(section->mr)) { 1189e5548617SBlue Swirl /* Normal RAM. */ 1190e4e69794SPaolo Bonzini iotlb = memory_region_get_ram_addr(section->mr) + xlat; 1191e5548617SBlue Swirl if (!section->readonly) { 1192b41aac4fSLiu Ping Fan iotlb |= PHYS_SECTION_NOTDIRTY; 1193e5548617SBlue Swirl } else { 1194b41aac4fSLiu Ping Fan iotlb |= PHYS_SECTION_ROM; 1195e5548617SBlue Swirl } 1196e5548617SBlue Swirl } else { 11970b8e2c10SPeter Maydell AddressSpaceDispatch *d; 11980b8e2c10SPeter Maydell 11990b8e2c10SPeter Maydell d = atomic_rcu_read(§ion->address_space->dispatch); 12000b8e2c10SPeter Maydell iotlb = section - d->map.sections; 1201149f54b5SPaolo Bonzini iotlb += xlat; 1202e5548617SBlue Swirl } 1203e5548617SBlue Swirl 1204e5548617SBlue Swirl /* Make accesses to pages with watchpoints go via the 1205e5548617SBlue Swirl watchpoint trap routines. */ 1206ff4700b0SAndreas Färber QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { 120705068c0dSPeter Maydell if (cpu_watchpoint_address_matches(wp, vaddr, TARGET_PAGE_SIZE)) { 1208e5548617SBlue Swirl /* Avoid trapping reads of pages with a write breakpoint. */ 1209e5548617SBlue Swirl if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) { 1210b41aac4fSLiu Ping Fan iotlb = PHYS_SECTION_WATCH + paddr; 1211e5548617SBlue Swirl *address |= TLB_MMIO; 1212e5548617SBlue Swirl break; 1213e5548617SBlue Swirl } 1214e5548617SBlue Swirl } 1215e5548617SBlue Swirl } 1216e5548617SBlue Swirl 1217e5548617SBlue Swirl return iotlb; 1218e5548617SBlue Swirl } 12199fa3e853Sbellard #endif /* defined(CONFIG_USER_ONLY) */ 122033417e70Sbellard 1221e2eef170Spbrook #if !defined(CONFIG_USER_ONLY) 12228da3ff18Spbrook 1223c227f099SAnthony Liguori static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, 12245312bd8bSAvi Kivity uint16_t section); 1225acc9d80bSJan Kiszka static subpage_t *subpage_init(AddressSpace *as, hwaddr base); 122654688b1eSAvi Kivity 1227a2b257d6SIgor Mammedov static void *(*phys_mem_alloc)(size_t size, uint64_t *align) = 1228a2b257d6SIgor Mammedov qemu_anon_ram_alloc; 122991138037SMarkus Armbruster 123091138037SMarkus Armbruster /* 123191138037SMarkus Armbruster * Set a custom physical guest memory alloator. 123291138037SMarkus Armbruster * Accelerators with unusual needs may need this. Hopefully, we can 123391138037SMarkus Armbruster * get rid of it eventually. 123491138037SMarkus Armbruster */ 1235a2b257d6SIgor Mammedov void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align)) 123691138037SMarkus Armbruster { 123791138037SMarkus Armbruster phys_mem_alloc = alloc; 123891138037SMarkus Armbruster } 123991138037SMarkus Armbruster 124053cb28cbSMarcel Apfelbaum static uint16_t phys_section_add(PhysPageMap *map, 124153cb28cbSMarcel Apfelbaum MemoryRegionSection *section) 12425312bd8bSAvi Kivity { 124368f3f65bSPaolo Bonzini /* The physical section number is ORed with a page-aligned 124468f3f65bSPaolo Bonzini * pointer to produce the iotlb entries. Thus it should 124568f3f65bSPaolo Bonzini * never overflow into the page-aligned value. 124668f3f65bSPaolo Bonzini */ 124753cb28cbSMarcel Apfelbaum assert(map->sections_nb < TARGET_PAGE_SIZE); 124868f3f65bSPaolo Bonzini 124953cb28cbSMarcel Apfelbaum if (map->sections_nb == map->sections_nb_alloc) { 125053cb28cbSMarcel Apfelbaum map->sections_nb_alloc = MAX(map->sections_nb_alloc * 2, 16); 125153cb28cbSMarcel Apfelbaum map->sections = g_renew(MemoryRegionSection, map->sections, 125253cb28cbSMarcel Apfelbaum map->sections_nb_alloc); 12535312bd8bSAvi Kivity } 125453cb28cbSMarcel Apfelbaum map->sections[map->sections_nb] = *section; 1255dfde4e6eSPaolo Bonzini memory_region_ref(section->mr); 125653cb28cbSMarcel Apfelbaum return map->sections_nb++; 12575312bd8bSAvi Kivity } 12585312bd8bSAvi Kivity 1259058bc4b5SPaolo Bonzini static void phys_section_destroy(MemoryRegion *mr) 1260058bc4b5SPaolo Bonzini { 126155b4e80bSDon Slutz bool have_sub_page = mr->subpage; 126255b4e80bSDon Slutz 1263dfde4e6eSPaolo Bonzini memory_region_unref(mr); 1264dfde4e6eSPaolo Bonzini 126555b4e80bSDon Slutz if (have_sub_page) { 1266058bc4b5SPaolo Bonzini subpage_t *subpage = container_of(mr, subpage_t, iomem); 1267b4fefef9SPeter Crosthwaite object_unref(OBJECT(&subpage->iomem)); 1268058bc4b5SPaolo Bonzini g_free(subpage); 1269058bc4b5SPaolo Bonzini } 1270058bc4b5SPaolo Bonzini } 1271058bc4b5SPaolo Bonzini 12726092666eSPaolo Bonzini static void phys_sections_free(PhysPageMap *map) 12735312bd8bSAvi Kivity { 12749affd6fcSPaolo Bonzini while (map->sections_nb > 0) { 12759affd6fcSPaolo Bonzini MemoryRegionSection *section = &map->sections[--map->sections_nb]; 1276058bc4b5SPaolo Bonzini phys_section_destroy(section->mr); 1277058bc4b5SPaolo Bonzini } 12789affd6fcSPaolo Bonzini g_free(map->sections); 12799affd6fcSPaolo Bonzini g_free(map->nodes); 12805312bd8bSAvi Kivity } 12815312bd8bSAvi Kivity 1282ac1970fbSAvi Kivity static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *section) 12830f0cb164SAvi Kivity { 12840f0cb164SAvi Kivity subpage_t *subpage; 1285a8170e5eSAvi Kivity hwaddr base = section->offset_within_address_space 12860f0cb164SAvi Kivity & TARGET_PAGE_MASK; 128797115a8dSMichael S. Tsirkin MemoryRegionSection *existing = phys_page_find(d->phys_map, base, 128853cb28cbSMarcel Apfelbaum d->map.nodes, d->map.sections); 12890f0cb164SAvi Kivity MemoryRegionSection subsection = { 12900f0cb164SAvi Kivity .offset_within_address_space = base, 1291052e87b0SPaolo Bonzini .size = int128_make64(TARGET_PAGE_SIZE), 12920f0cb164SAvi Kivity }; 1293a8170e5eSAvi Kivity hwaddr start, end; 12940f0cb164SAvi Kivity 1295f3705d53SAvi Kivity assert(existing->mr->subpage || existing->mr == &io_mem_unassigned); 12960f0cb164SAvi Kivity 1297f3705d53SAvi Kivity if (!(existing->mr->subpage)) { 1298acc9d80bSJan Kiszka subpage = subpage_init(d->as, base); 12993be91e86SEdgar E. Iglesias subsection.address_space = d->as; 13000f0cb164SAvi Kivity subsection.mr = &subpage->iomem; 1301ac1970fbSAvi Kivity phys_page_set(d, base >> TARGET_PAGE_BITS, 1, 130253cb28cbSMarcel Apfelbaum phys_section_add(&d->map, &subsection)); 13030f0cb164SAvi Kivity } else { 1304f3705d53SAvi Kivity subpage = container_of(existing->mr, subpage_t, iomem); 13050f0cb164SAvi Kivity } 13060f0cb164SAvi Kivity start = section->offset_within_address_space & ~TARGET_PAGE_MASK; 1307052e87b0SPaolo Bonzini end = start + int128_get64(section->size) - 1; 130853cb28cbSMarcel Apfelbaum subpage_register(subpage, start, end, 130953cb28cbSMarcel Apfelbaum phys_section_add(&d->map, section)); 13100f0cb164SAvi Kivity } 13110f0cb164SAvi Kivity 13120f0cb164SAvi Kivity 1313052e87b0SPaolo Bonzini static void register_multipage(AddressSpaceDispatch *d, 1314052e87b0SPaolo Bonzini MemoryRegionSection *section) 131533417e70Sbellard { 1316a8170e5eSAvi Kivity hwaddr start_addr = section->offset_within_address_space; 131753cb28cbSMarcel Apfelbaum uint16_t section_index = phys_section_add(&d->map, section); 1318052e87b0SPaolo Bonzini uint64_t num_pages = int128_get64(int128_rshift(section->size, 1319052e87b0SPaolo Bonzini TARGET_PAGE_BITS)); 1320dd81124bSAvi Kivity 1321733d5ef5SPaolo Bonzini assert(num_pages); 1322733d5ef5SPaolo Bonzini phys_page_set(d, start_addr >> TARGET_PAGE_BITS, num_pages, section_index); 132333417e70Sbellard } 132433417e70Sbellard 1325ac1970fbSAvi Kivity static void mem_add(MemoryListener *listener, MemoryRegionSection *section) 13260f0cb164SAvi Kivity { 132789ae337aSPaolo Bonzini AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener); 132800752703SPaolo Bonzini AddressSpaceDispatch *d = as->next_dispatch; 132999b9cc06SPaolo Bonzini MemoryRegionSection now = *section, remain = *section; 1330052e87b0SPaolo Bonzini Int128 page_size = int128_make64(TARGET_PAGE_SIZE); 13310f0cb164SAvi Kivity 1332733d5ef5SPaolo Bonzini if (now.offset_within_address_space & ~TARGET_PAGE_MASK) { 1333733d5ef5SPaolo Bonzini uint64_t left = TARGET_PAGE_ALIGN(now.offset_within_address_space) 1334733d5ef5SPaolo Bonzini - now.offset_within_address_space; 1335733d5ef5SPaolo Bonzini 1336052e87b0SPaolo Bonzini now.size = int128_min(int128_make64(left), now.size); 1337ac1970fbSAvi Kivity register_subpage(d, &now); 1338733d5ef5SPaolo Bonzini } else { 1339052e87b0SPaolo Bonzini now.size = int128_zero(); 1340733d5ef5SPaolo Bonzini } 1341052e87b0SPaolo Bonzini while (int128_ne(remain.size, now.size)) { 1342052e87b0SPaolo Bonzini remain.size = int128_sub(remain.size, now.size); 1343052e87b0SPaolo Bonzini remain.offset_within_address_space += int128_get64(now.size); 1344052e87b0SPaolo Bonzini remain.offset_within_region += int128_get64(now.size); 13450f0cb164SAvi Kivity now = remain; 1346052e87b0SPaolo Bonzini if (int128_lt(remain.size, page_size)) { 1347733d5ef5SPaolo Bonzini register_subpage(d, &now); 134888266249SHu Tao } else if (remain.offset_within_address_space & ~TARGET_PAGE_MASK) { 1349052e87b0SPaolo Bonzini now.size = page_size; 1350ac1970fbSAvi Kivity register_subpage(d, &now); 135169b67646STyler Hall } else { 1352052e87b0SPaolo Bonzini now.size = int128_and(now.size, int128_neg(page_size)); 1353ac1970fbSAvi Kivity register_multipage(d, &now); 135469b67646STyler Hall } 13550f0cb164SAvi Kivity } 13560f0cb164SAvi Kivity } 13570f0cb164SAvi Kivity 135862a2744cSSheng Yang void qemu_flush_coalesced_mmio_buffer(void) 135962a2744cSSheng Yang { 136062a2744cSSheng Yang if (kvm_enabled()) 136162a2744cSSheng Yang kvm_flush_coalesced_mmio_buffer(); 136262a2744cSSheng Yang } 136362a2744cSSheng Yang 1364b2a8658eSUmesh Deshpande void qemu_mutex_lock_ramlist(void) 1365b2a8658eSUmesh Deshpande { 1366b2a8658eSUmesh Deshpande qemu_mutex_lock(&ram_list.mutex); 1367b2a8658eSUmesh Deshpande } 1368b2a8658eSUmesh Deshpande 1369b2a8658eSUmesh Deshpande void qemu_mutex_unlock_ramlist(void) 1370b2a8658eSUmesh Deshpande { 1371b2a8658eSUmesh Deshpande qemu_mutex_unlock(&ram_list.mutex); 1372b2a8658eSUmesh Deshpande } 1373b2a8658eSUmesh Deshpande 1374be9b23c4SPeter Xu void ram_block_dump(Monitor *mon) 1375be9b23c4SPeter Xu { 1376be9b23c4SPeter Xu RAMBlock *block; 1377be9b23c4SPeter Xu char *psize; 1378be9b23c4SPeter Xu 1379be9b23c4SPeter Xu rcu_read_lock(); 1380be9b23c4SPeter Xu monitor_printf(mon, "%24s %8s %18s %18s %18s\n", 1381be9b23c4SPeter Xu "Block Name", "PSize", "Offset", "Used", "Total"); 1382be9b23c4SPeter Xu RAMBLOCK_FOREACH(block) { 1383be9b23c4SPeter Xu psize = size_to_str(block->page_size); 1384be9b23c4SPeter Xu monitor_printf(mon, "%24s %8s 0x%016" PRIx64 " 0x%016" PRIx64 1385be9b23c4SPeter Xu " 0x%016" PRIx64 "\n", block->idstr, psize, 1386be9b23c4SPeter Xu (uint64_t)block->offset, 1387be9b23c4SPeter Xu (uint64_t)block->used_length, 1388be9b23c4SPeter Xu (uint64_t)block->max_length); 1389be9b23c4SPeter Xu g_free(psize); 1390be9b23c4SPeter Xu } 1391be9b23c4SPeter Xu rcu_read_unlock(); 1392be9b23c4SPeter Xu } 1393be9b23c4SPeter Xu 1394e1e84ba0SMarkus Armbruster #ifdef __linux__ 13959c607668SAlexey Kardashevskiy /* 13969c607668SAlexey Kardashevskiy * FIXME TOCTTOU: this iterates over memory backends' mem-path, which 13979c607668SAlexey Kardashevskiy * may or may not name the same files / on the same filesystem now as 13989c607668SAlexey Kardashevskiy * when we actually open and map them. Iterate over the file 13999c607668SAlexey Kardashevskiy * descriptors instead, and use qemu_fd_getpagesize(). 14009c607668SAlexey Kardashevskiy */ 14019c607668SAlexey Kardashevskiy static int find_max_supported_pagesize(Object *obj, void *opaque) 14029c607668SAlexey Kardashevskiy { 14039c607668SAlexey Kardashevskiy char *mem_path; 14049c607668SAlexey Kardashevskiy long *hpsize_min = opaque; 14059c607668SAlexey Kardashevskiy 14069c607668SAlexey Kardashevskiy if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) { 14079c607668SAlexey Kardashevskiy mem_path = object_property_get_str(obj, "mem-path", NULL); 14089c607668SAlexey Kardashevskiy if (mem_path) { 14099c607668SAlexey Kardashevskiy long hpsize = qemu_mempath_getpagesize(mem_path); 14109c607668SAlexey Kardashevskiy if (hpsize < *hpsize_min) { 14119c607668SAlexey Kardashevskiy *hpsize_min = hpsize; 14129c607668SAlexey Kardashevskiy } 14139c607668SAlexey Kardashevskiy } else { 14149c607668SAlexey Kardashevskiy *hpsize_min = getpagesize(); 14159c607668SAlexey Kardashevskiy } 14169c607668SAlexey Kardashevskiy } 14179c607668SAlexey Kardashevskiy 14189c607668SAlexey Kardashevskiy return 0; 14199c607668SAlexey Kardashevskiy } 14209c607668SAlexey Kardashevskiy 14219c607668SAlexey Kardashevskiy long qemu_getrampagesize(void) 14229c607668SAlexey Kardashevskiy { 14239c607668SAlexey Kardashevskiy long hpsize = LONG_MAX; 14249c607668SAlexey Kardashevskiy long mainrampagesize; 14259c607668SAlexey Kardashevskiy Object *memdev_root; 14269c607668SAlexey Kardashevskiy 14279c607668SAlexey Kardashevskiy if (mem_path) { 14289c607668SAlexey Kardashevskiy mainrampagesize = qemu_mempath_getpagesize(mem_path); 14299c607668SAlexey Kardashevskiy } else { 14309c607668SAlexey Kardashevskiy mainrampagesize = getpagesize(); 14319c607668SAlexey Kardashevskiy } 14329c607668SAlexey Kardashevskiy 14339c607668SAlexey Kardashevskiy /* it's possible we have memory-backend objects with 14349c607668SAlexey Kardashevskiy * hugepage-backed RAM. these may get mapped into system 14359c607668SAlexey Kardashevskiy * address space via -numa parameters or memory hotplug 14369c607668SAlexey Kardashevskiy * hooks. we want to take these into account, but we 14379c607668SAlexey Kardashevskiy * also want to make sure these supported hugepage 14389c607668SAlexey Kardashevskiy * sizes are applicable across the entire range of memory 14399c607668SAlexey Kardashevskiy * we may boot from, so we take the min across all 14409c607668SAlexey Kardashevskiy * backends, and assume normal pages in cases where a 14419c607668SAlexey Kardashevskiy * backend isn't backed by hugepages. 14429c607668SAlexey Kardashevskiy */ 14439c607668SAlexey Kardashevskiy memdev_root = object_resolve_path("/objects", NULL); 14449c607668SAlexey Kardashevskiy if (memdev_root) { 14459c607668SAlexey Kardashevskiy object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize); 14469c607668SAlexey Kardashevskiy } 14479c607668SAlexey Kardashevskiy if (hpsize == LONG_MAX) { 14489c607668SAlexey Kardashevskiy /* No additional memory regions found ==> Report main RAM page size */ 14499c607668SAlexey Kardashevskiy return mainrampagesize; 14509c607668SAlexey Kardashevskiy } 14519c607668SAlexey Kardashevskiy 14529c607668SAlexey Kardashevskiy /* If NUMA is disabled or the NUMA nodes are not backed with a 14539c607668SAlexey Kardashevskiy * memory-backend, then there is at least one node using "normal" RAM, 14549c607668SAlexey Kardashevskiy * so if its page size is smaller we have got to report that size instead. 14559c607668SAlexey Kardashevskiy */ 14569c607668SAlexey Kardashevskiy if (hpsize > mainrampagesize && 14579c607668SAlexey Kardashevskiy (nb_numa_nodes == 0 || numa_info[0].node_memdev == NULL)) { 14589c607668SAlexey Kardashevskiy static bool warned; 14599c607668SAlexey Kardashevskiy if (!warned) { 14609c607668SAlexey Kardashevskiy error_report("Huge page support disabled (n/a for main memory)."); 14619c607668SAlexey Kardashevskiy warned = true; 14629c607668SAlexey Kardashevskiy } 14639c607668SAlexey Kardashevskiy return mainrampagesize; 14649c607668SAlexey Kardashevskiy } 14659c607668SAlexey Kardashevskiy 14669c607668SAlexey Kardashevskiy return hpsize; 14679c607668SAlexey Kardashevskiy } 14689c607668SAlexey Kardashevskiy #else 14699c607668SAlexey Kardashevskiy long qemu_getrampagesize(void) 14709c607668SAlexey Kardashevskiy { 14719c607668SAlexey Kardashevskiy return getpagesize(); 14729c607668SAlexey Kardashevskiy } 14739c607668SAlexey Kardashevskiy #endif 14749c607668SAlexey Kardashevskiy 14759c607668SAlexey Kardashevskiy #ifdef __linux__ 1476d6af99c9SHaozhong Zhang static int64_t get_file_size(int fd) 1477d6af99c9SHaozhong Zhang { 1478d6af99c9SHaozhong Zhang int64_t size = lseek(fd, 0, SEEK_END); 1479d6af99c9SHaozhong Zhang if (size < 0) { 1480d6af99c9SHaozhong Zhang return -errno; 1481d6af99c9SHaozhong Zhang } 1482d6af99c9SHaozhong Zhang return size; 1483d6af99c9SHaozhong Zhang } 1484d6af99c9SHaozhong Zhang 148504b16653SAlex Williamson static void *file_ram_alloc(RAMBlock *block, 148604b16653SAlex Williamson ram_addr_t memory, 14877f56e740SPaolo Bonzini const char *path, 14887f56e740SPaolo Bonzini Error **errp) 1489c902760fSMarcelo Tosatti { 1490fd97fd44SMarkus Armbruster bool unlink_on_error = false; 1491c902760fSMarcelo Tosatti char *filename; 14928ca761f6SPeter Feiner char *sanitized_name; 14938ca761f6SPeter Feiner char *c; 1494056b68afSIgor Mammedov void *area = MAP_FAILED; 14955c3ece79SPaolo Bonzini int fd = -1; 1496d6af99c9SHaozhong Zhang int64_t file_size; 1497c902760fSMarcelo Tosatti 1498c902760fSMarcelo Tosatti if (kvm_enabled() && !kvm_has_sync_mmu()) { 14997f56e740SPaolo Bonzini error_setg(errp, 15007f56e740SPaolo Bonzini "host lacks kvm mmu notifiers, -mem-path unsupported"); 1501fd97fd44SMarkus Armbruster return NULL; 1502c902760fSMarcelo Tosatti } 1503c902760fSMarcelo Tosatti 1504fd97fd44SMarkus Armbruster for (;;) { 1505fd97fd44SMarkus Armbruster fd = open(path, O_RDWR); 1506fd97fd44SMarkus Armbruster if (fd >= 0) { 1507fd97fd44SMarkus Armbruster /* @path names an existing file, use it */ 1508fd97fd44SMarkus Armbruster break; 1509fd97fd44SMarkus Armbruster } 1510fd97fd44SMarkus Armbruster if (errno == ENOENT) { 1511fd97fd44SMarkus Armbruster /* @path names a file that doesn't exist, create it */ 1512fd97fd44SMarkus Armbruster fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0644); 1513fd97fd44SMarkus Armbruster if (fd >= 0) { 1514fd97fd44SMarkus Armbruster unlink_on_error = true; 1515fd97fd44SMarkus Armbruster break; 1516fd97fd44SMarkus Armbruster } 1517fd97fd44SMarkus Armbruster } else if (errno == EISDIR) { 1518fd97fd44SMarkus Armbruster /* @path names a directory, create a file there */ 15198ca761f6SPeter Feiner /* Make name safe to use with mkstemp by replacing '/' with '_'. */ 152083234bf2SPeter Crosthwaite sanitized_name = g_strdup(memory_region_name(block->mr)); 15218ca761f6SPeter Feiner for (c = sanitized_name; *c != '\0'; c++) { 15228d31d6b6SPavel Fedin if (*c == '/') { 15238ca761f6SPeter Feiner *c = '_'; 15248ca761f6SPeter Feiner } 15258d31d6b6SPavel Fedin } 15268ca761f6SPeter Feiner 15278ca761f6SPeter Feiner filename = g_strdup_printf("%s/qemu_back_mem.%s.XXXXXX", path, 15288ca761f6SPeter Feiner sanitized_name); 15298ca761f6SPeter Feiner g_free(sanitized_name); 1530c902760fSMarcelo Tosatti 1531c902760fSMarcelo Tosatti fd = mkstemp(filename); 15328d31d6b6SPavel Fedin if (fd >= 0) { 15338d31d6b6SPavel Fedin unlink(filename); 1534fd97fd44SMarkus Armbruster g_free(filename); 1535fd97fd44SMarkus Armbruster break; 15368d31d6b6SPavel Fedin } 15378d31d6b6SPavel Fedin g_free(filename); 1538fd97fd44SMarkus Armbruster } 1539fd97fd44SMarkus Armbruster if (errno != EEXIST && errno != EINTR) { 1540fd97fd44SMarkus Armbruster error_setg_errno(errp, errno, 1541fd97fd44SMarkus Armbruster "can't open backing store %s for guest RAM", 1542fd97fd44SMarkus Armbruster path); 1543fd97fd44SMarkus Armbruster goto error; 1544fd97fd44SMarkus Armbruster } 1545fd97fd44SMarkus Armbruster /* 1546fd97fd44SMarkus Armbruster * Try again on EINTR and EEXIST. The latter happens when 1547fd97fd44SMarkus Armbruster * something else creates the file between our two open(). 1548fd97fd44SMarkus Armbruster */ 15498d31d6b6SPavel Fedin } 15508d31d6b6SPavel Fedin 1551863e9621SDr. David Alan Gilbert block->page_size = qemu_fd_getpagesize(fd); 15528360668eSHaozhong Zhang block->mr->align = block->page_size; 15538360668eSHaozhong Zhang #if defined(__s390x__) 15548360668eSHaozhong Zhang if (kvm_enabled()) { 15558360668eSHaozhong Zhang block->mr->align = MAX(block->mr->align, QEMU_VMALLOC_ALIGN); 15568360668eSHaozhong Zhang } 15578360668eSHaozhong Zhang #endif 1558fd97fd44SMarkus Armbruster 1559d6af99c9SHaozhong Zhang file_size = get_file_size(fd); 1560d6af99c9SHaozhong Zhang 1561863e9621SDr. David Alan Gilbert if (memory < block->page_size) { 1562fd97fd44SMarkus Armbruster error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to " 1563863e9621SDr. David Alan Gilbert "or larger than page size 0x%zx", 1564863e9621SDr. David Alan Gilbert memory, block->page_size); 1565f9a49dfaSMarcelo Tosatti goto error; 1566c902760fSMarcelo Tosatti } 1567c902760fSMarcelo Tosatti 15681775f111SHaozhong Zhang if (file_size > 0 && file_size < memory) { 15691775f111SHaozhong Zhang error_setg(errp, "backing store %s size 0x%" PRIx64 15701775f111SHaozhong Zhang " does not match 'size' option 0x" RAM_ADDR_FMT, 15711775f111SHaozhong Zhang path, file_size, memory); 15721775f111SHaozhong Zhang goto error; 15731775f111SHaozhong Zhang } 15741775f111SHaozhong Zhang 1575863e9621SDr. David Alan Gilbert memory = ROUND_UP(memory, block->page_size); 1576c902760fSMarcelo Tosatti 1577c902760fSMarcelo Tosatti /* 1578c902760fSMarcelo Tosatti * ftruncate is not supported by hugetlbfs in older 1579c902760fSMarcelo Tosatti * hosts, so don't bother bailing out on errors. 1580c902760fSMarcelo Tosatti * If anything goes wrong with it under other filesystems, 1581c902760fSMarcelo Tosatti * mmap will fail. 1582d6af99c9SHaozhong Zhang * 1583d6af99c9SHaozhong Zhang * Do not truncate the non-empty backend file to avoid corrupting 1584d6af99c9SHaozhong Zhang * the existing data in the file. Disabling shrinking is not 1585d6af99c9SHaozhong Zhang * enough. For example, the current vNVDIMM implementation stores 1586d6af99c9SHaozhong Zhang * the guest NVDIMM labels at the end of the backend file. If the 1587d6af99c9SHaozhong Zhang * backend file is later extended, QEMU will not be able to find 1588d6af99c9SHaozhong Zhang * those labels. Therefore, extending the non-empty backend file 1589d6af99c9SHaozhong Zhang * is disabled as well. 1590c902760fSMarcelo Tosatti */ 1591d6af99c9SHaozhong Zhang if (!file_size && ftruncate(fd, memory)) { 1592c902760fSMarcelo Tosatti perror("ftruncate"); 15937f56e740SPaolo Bonzini } 1594c902760fSMarcelo Tosatti 1595d2f39addSDominik Dingel area = qemu_ram_mmap(fd, memory, block->mr->align, 1596d2f39addSDominik Dingel block->flags & RAM_SHARED); 1597c902760fSMarcelo Tosatti if (area == MAP_FAILED) { 15987f56e740SPaolo Bonzini error_setg_errno(errp, errno, 1599fd97fd44SMarkus Armbruster "unable to map backing store for guest RAM"); 1600f9a49dfaSMarcelo Tosatti goto error; 1601c902760fSMarcelo Tosatti } 1602ef36fa14SMarcelo Tosatti 1603ef36fa14SMarcelo Tosatti if (mem_prealloc) { 16041e356fc1SJitendra Kolhe os_mem_prealloc(fd, area, memory, smp_cpus, errp); 1605056b68afSIgor Mammedov if (errp && *errp) { 1606056b68afSIgor Mammedov goto error; 1607056b68afSIgor Mammedov } 1608ef36fa14SMarcelo Tosatti } 1609ef36fa14SMarcelo Tosatti 161004b16653SAlex Williamson block->fd = fd; 1611c902760fSMarcelo Tosatti return area; 1612f9a49dfaSMarcelo Tosatti 1613f9a49dfaSMarcelo Tosatti error: 1614056b68afSIgor Mammedov if (area != MAP_FAILED) { 1615056b68afSIgor Mammedov qemu_ram_munmap(area, memory); 1616056b68afSIgor Mammedov } 1617fd97fd44SMarkus Armbruster if (unlink_on_error) { 1618fd97fd44SMarkus Armbruster unlink(path); 1619fd97fd44SMarkus Armbruster } 16205c3ece79SPaolo Bonzini if (fd != -1) { 1621fd97fd44SMarkus Armbruster close(fd); 16225c3ece79SPaolo Bonzini } 1623f9a49dfaSMarcelo Tosatti return NULL; 1624c902760fSMarcelo Tosatti } 1625c902760fSMarcelo Tosatti #endif 1626c902760fSMarcelo Tosatti 16270dc3f44aSMike Day /* Called with the ramlist lock held. */ 1628d17b5288SAlex Williamson static ram_addr_t find_ram_offset(ram_addr_t size) 1629d17b5288SAlex Williamson { 163004b16653SAlex Williamson RAMBlock *block, *next_block; 16313e837b2cSAlex Williamson ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX; 163204b16653SAlex Williamson 163349cd9ac6SStefan Hajnoczi assert(size != 0); /* it would hand out same offset multiple times */ 163449cd9ac6SStefan Hajnoczi 16350dc3f44aSMike Day if (QLIST_EMPTY_RCU(&ram_list.blocks)) { 163604b16653SAlex Williamson return 0; 16370d53d9feSMike Day } 163804b16653SAlex Williamson 163999e15582SPeter Xu RAMBLOCK_FOREACH(block) { 1640f15fbc4bSAnthony PERARD ram_addr_t end, next = RAM_ADDR_MAX; 164104b16653SAlex Williamson 164262be4e3aSMichael S. Tsirkin end = block->offset + block->max_length; 164304b16653SAlex Williamson 164499e15582SPeter Xu RAMBLOCK_FOREACH(next_block) { 164504b16653SAlex Williamson if (next_block->offset >= end) { 164604b16653SAlex Williamson next = MIN(next, next_block->offset); 164704b16653SAlex Williamson } 164804b16653SAlex Williamson } 164904b16653SAlex Williamson if (next - end >= size && next - end < mingap) { 165004b16653SAlex Williamson offset = end; 165104b16653SAlex Williamson mingap = next - end; 165204b16653SAlex Williamson } 165304b16653SAlex Williamson } 16543e837b2cSAlex Williamson 16553e837b2cSAlex Williamson if (offset == RAM_ADDR_MAX) { 16563e837b2cSAlex Williamson fprintf(stderr, "Failed to find gap of requested size: %" PRIu64 "\n", 16573e837b2cSAlex Williamson (uint64_t)size); 16583e837b2cSAlex Williamson abort(); 16593e837b2cSAlex Williamson } 16603e837b2cSAlex Williamson 166104b16653SAlex Williamson return offset; 166204b16653SAlex Williamson } 166304b16653SAlex Williamson 1664b8c48993SJuan Quintela unsigned long last_ram_page(void) 166504b16653SAlex Williamson { 1666d17b5288SAlex Williamson RAMBlock *block; 1667d17b5288SAlex Williamson ram_addr_t last = 0; 1668d17b5288SAlex Williamson 16690dc3f44aSMike Day rcu_read_lock(); 167099e15582SPeter Xu RAMBLOCK_FOREACH(block) { 167162be4e3aSMichael S. Tsirkin last = MAX(last, block->offset + block->max_length); 16720d53d9feSMike Day } 16730dc3f44aSMike Day rcu_read_unlock(); 1674b8c48993SJuan Quintela return last >> TARGET_PAGE_BITS; 1675d17b5288SAlex Williamson } 1676d17b5288SAlex Williamson 1677ddb97f1dSJason Baron static void qemu_ram_setup_dump(void *addr, ram_addr_t size) 1678ddb97f1dSJason Baron { 1679ddb97f1dSJason Baron int ret; 1680ddb97f1dSJason Baron 1681ddb97f1dSJason Baron /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */ 168247c8ca53SMarcel Apfelbaum if (!machine_dump_guest_core(current_machine)) { 1683ddb97f1dSJason Baron ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP); 1684ddb97f1dSJason Baron if (ret) { 1685ddb97f1dSJason Baron perror("qemu_madvise"); 1686ddb97f1dSJason Baron fprintf(stderr, "madvise doesn't support MADV_DONTDUMP, " 1687ddb97f1dSJason Baron "but dump_guest_core=off specified\n"); 1688ddb97f1dSJason Baron } 1689ddb97f1dSJason Baron } 1690ddb97f1dSJason Baron } 1691ddb97f1dSJason Baron 1692422148d3SDr. David Alan Gilbert const char *qemu_ram_get_idstr(RAMBlock *rb) 1693422148d3SDr. David Alan Gilbert { 1694422148d3SDr. David Alan Gilbert return rb->idstr; 1695422148d3SDr. David Alan Gilbert } 1696422148d3SDr. David Alan Gilbert 1697463a4ac2SDr. David Alan Gilbert bool qemu_ram_is_shared(RAMBlock *rb) 1698463a4ac2SDr. David Alan Gilbert { 1699463a4ac2SDr. David Alan Gilbert return rb->flags & RAM_SHARED; 1700463a4ac2SDr. David Alan Gilbert } 1701463a4ac2SDr. David Alan Gilbert 1702ae3a7047SMike Day /* Called with iothread lock held. */ 1703fa53a0e5SGonglei void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev) 170420cfe881SHu Tao { 1705fa53a0e5SGonglei RAMBlock *block; 170620cfe881SHu Tao 1707c5705a77SAvi Kivity assert(new_block); 1708c5705a77SAvi Kivity assert(!new_block->idstr[0]); 170984b89d78SCam Macdonell 171009e5ab63SAnthony Liguori if (dev) { 171109e5ab63SAnthony Liguori char *id = qdev_get_dev_path(dev); 171284b89d78SCam Macdonell if (id) { 171384b89d78SCam Macdonell snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id); 17147267c094SAnthony Liguori g_free(id); 171584b89d78SCam Macdonell } 171684b89d78SCam Macdonell } 171784b89d78SCam Macdonell pstrcat(new_block->idstr, sizeof(new_block->idstr), name); 171884b89d78SCam Macdonell 1719ab0a9956SGonglei rcu_read_lock(); 172099e15582SPeter Xu RAMBLOCK_FOREACH(block) { 1721fa53a0e5SGonglei if (block != new_block && 1722fa53a0e5SGonglei !strcmp(block->idstr, new_block->idstr)) { 172384b89d78SCam Macdonell fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n", 172484b89d78SCam Macdonell new_block->idstr); 172584b89d78SCam Macdonell abort(); 172684b89d78SCam Macdonell } 172784b89d78SCam Macdonell } 17280dc3f44aSMike Day rcu_read_unlock(); 1729c5705a77SAvi Kivity } 1730c5705a77SAvi Kivity 1731ae3a7047SMike Day /* Called with iothread lock held. */ 1732fa53a0e5SGonglei void qemu_ram_unset_idstr(RAMBlock *block) 173320cfe881SHu Tao { 1734ae3a7047SMike Day /* FIXME: arch_init.c assumes that this is not called throughout 1735ae3a7047SMike Day * migration. Ignore the problem since hot-unplug during migration 1736ae3a7047SMike Day * does not work anyway. 1737ae3a7047SMike Day */ 173820cfe881SHu Tao if (block) { 173920cfe881SHu Tao memset(block->idstr, 0, sizeof(block->idstr)); 174020cfe881SHu Tao } 174120cfe881SHu Tao } 174220cfe881SHu Tao 1743863e9621SDr. David Alan Gilbert size_t qemu_ram_pagesize(RAMBlock *rb) 1744863e9621SDr. David Alan Gilbert { 1745863e9621SDr. David Alan Gilbert return rb->page_size; 1746863e9621SDr. David Alan Gilbert } 1747863e9621SDr. David Alan Gilbert 174867f11b5cSDr. David Alan Gilbert /* Returns the largest size of page in use */ 174967f11b5cSDr. David Alan Gilbert size_t qemu_ram_pagesize_largest(void) 175067f11b5cSDr. David Alan Gilbert { 175167f11b5cSDr. David Alan Gilbert RAMBlock *block; 175267f11b5cSDr. David Alan Gilbert size_t largest = 0; 175367f11b5cSDr. David Alan Gilbert 175499e15582SPeter Xu RAMBLOCK_FOREACH(block) { 175567f11b5cSDr. David Alan Gilbert largest = MAX(largest, qemu_ram_pagesize(block)); 175667f11b5cSDr. David Alan Gilbert } 175767f11b5cSDr. David Alan Gilbert 175867f11b5cSDr. David Alan Gilbert return largest; 175967f11b5cSDr. David Alan Gilbert } 176067f11b5cSDr. David Alan Gilbert 17618490fc78SLuiz Capitulino static int memory_try_enable_merging(void *addr, size_t len) 17628490fc78SLuiz Capitulino { 176375cc7f01SMarcel Apfelbaum if (!machine_mem_merge(current_machine)) { 17648490fc78SLuiz Capitulino /* disabled by the user */ 17658490fc78SLuiz Capitulino return 0; 17668490fc78SLuiz Capitulino } 17678490fc78SLuiz Capitulino 17688490fc78SLuiz Capitulino return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE); 17698490fc78SLuiz Capitulino } 17708490fc78SLuiz Capitulino 177162be4e3aSMichael S. Tsirkin /* Only legal before guest might have detected the memory size: e.g. on 177262be4e3aSMichael S. Tsirkin * incoming migration, or right after reset. 177362be4e3aSMichael S. Tsirkin * 177462be4e3aSMichael S. Tsirkin * As memory core doesn't know how is memory accessed, it is up to 177562be4e3aSMichael S. Tsirkin * resize callback to update device state and/or add assertions to detect 177662be4e3aSMichael S. Tsirkin * misuse, if necessary. 177762be4e3aSMichael S. Tsirkin */ 1778fa53a0e5SGonglei int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp) 177962be4e3aSMichael S. Tsirkin { 178062be4e3aSMichael S. Tsirkin assert(block); 178162be4e3aSMichael S. Tsirkin 17824ed023ceSDr. David Alan Gilbert newsize = HOST_PAGE_ALIGN(newsize); 1783129ddaf3SMichael S. Tsirkin 178462be4e3aSMichael S. Tsirkin if (block->used_length == newsize) { 178562be4e3aSMichael S. Tsirkin return 0; 178662be4e3aSMichael S. Tsirkin } 178762be4e3aSMichael S. Tsirkin 178862be4e3aSMichael S. Tsirkin if (!(block->flags & RAM_RESIZEABLE)) { 178962be4e3aSMichael S. Tsirkin error_setg_errno(errp, EINVAL, 179062be4e3aSMichael S. Tsirkin "Length mismatch: %s: 0x" RAM_ADDR_FMT 179162be4e3aSMichael S. Tsirkin " in != 0x" RAM_ADDR_FMT, block->idstr, 179262be4e3aSMichael S. Tsirkin newsize, block->used_length); 179362be4e3aSMichael S. Tsirkin return -EINVAL; 179462be4e3aSMichael S. Tsirkin } 179562be4e3aSMichael S. Tsirkin 179662be4e3aSMichael S. Tsirkin if (block->max_length < newsize) { 179762be4e3aSMichael S. Tsirkin error_setg_errno(errp, EINVAL, 179862be4e3aSMichael S. Tsirkin "Length too large: %s: 0x" RAM_ADDR_FMT 179962be4e3aSMichael S. Tsirkin " > 0x" RAM_ADDR_FMT, block->idstr, 180062be4e3aSMichael S. Tsirkin newsize, block->max_length); 180162be4e3aSMichael S. Tsirkin return -EINVAL; 180262be4e3aSMichael S. Tsirkin } 180362be4e3aSMichael S. Tsirkin 180462be4e3aSMichael S. Tsirkin cpu_physical_memory_clear_dirty_range(block->offset, block->used_length); 180562be4e3aSMichael S. Tsirkin block->used_length = newsize; 180658d2707eSPaolo Bonzini cpu_physical_memory_set_dirty_range(block->offset, block->used_length, 180758d2707eSPaolo Bonzini DIRTY_CLIENTS_ALL); 180862be4e3aSMichael S. Tsirkin memory_region_set_size(block->mr, newsize); 180962be4e3aSMichael S. Tsirkin if (block->resized) { 181062be4e3aSMichael S. Tsirkin block->resized(block->idstr, newsize, block->host); 181162be4e3aSMichael S. Tsirkin } 181262be4e3aSMichael S. Tsirkin return 0; 181362be4e3aSMichael S. Tsirkin } 181462be4e3aSMichael S. Tsirkin 18155b82b703SStefan Hajnoczi /* Called with ram_list.mutex held */ 18165b82b703SStefan Hajnoczi static void dirty_memory_extend(ram_addr_t old_ram_size, 18175b82b703SStefan Hajnoczi ram_addr_t new_ram_size) 18185b82b703SStefan Hajnoczi { 18195b82b703SStefan Hajnoczi ram_addr_t old_num_blocks = DIV_ROUND_UP(old_ram_size, 18205b82b703SStefan Hajnoczi DIRTY_MEMORY_BLOCK_SIZE); 18215b82b703SStefan Hajnoczi ram_addr_t new_num_blocks = DIV_ROUND_UP(new_ram_size, 18225b82b703SStefan Hajnoczi DIRTY_MEMORY_BLOCK_SIZE); 18235b82b703SStefan Hajnoczi int i; 18245b82b703SStefan Hajnoczi 18255b82b703SStefan Hajnoczi /* Only need to extend if block count increased */ 18265b82b703SStefan Hajnoczi if (new_num_blocks <= old_num_blocks) { 18275b82b703SStefan Hajnoczi return; 18285b82b703SStefan Hajnoczi } 18295b82b703SStefan Hajnoczi 18305b82b703SStefan Hajnoczi for (i = 0; i < DIRTY_MEMORY_NUM; i++) { 18315b82b703SStefan Hajnoczi DirtyMemoryBlocks *old_blocks; 18325b82b703SStefan Hajnoczi DirtyMemoryBlocks *new_blocks; 18335b82b703SStefan Hajnoczi int j; 18345b82b703SStefan Hajnoczi 18355b82b703SStefan Hajnoczi old_blocks = atomic_rcu_read(&ram_list.dirty_memory[i]); 18365b82b703SStefan Hajnoczi new_blocks = g_malloc(sizeof(*new_blocks) + 18375b82b703SStefan Hajnoczi sizeof(new_blocks->blocks[0]) * new_num_blocks); 18385b82b703SStefan Hajnoczi 18395b82b703SStefan Hajnoczi if (old_num_blocks) { 18405b82b703SStefan Hajnoczi memcpy(new_blocks->blocks, old_blocks->blocks, 18415b82b703SStefan Hajnoczi old_num_blocks * sizeof(old_blocks->blocks[0])); 18425b82b703SStefan Hajnoczi } 18435b82b703SStefan Hajnoczi 18445b82b703SStefan Hajnoczi for (j = old_num_blocks; j < new_num_blocks; j++) { 18455b82b703SStefan Hajnoczi new_blocks->blocks[j] = bitmap_new(DIRTY_MEMORY_BLOCK_SIZE); 18465b82b703SStefan Hajnoczi } 18475b82b703SStefan Hajnoczi 18485b82b703SStefan Hajnoczi atomic_rcu_set(&ram_list.dirty_memory[i], new_blocks); 18495b82b703SStefan Hajnoczi 18505b82b703SStefan Hajnoczi if (old_blocks) { 18515b82b703SStefan Hajnoczi g_free_rcu(old_blocks, rcu); 18525b82b703SStefan Hajnoczi } 18535b82b703SStefan Hajnoczi } 18545b82b703SStefan Hajnoczi } 18555b82b703SStefan Hajnoczi 1856528f46afSFam Zheng static void ram_block_add(RAMBlock *new_block, Error **errp) 1857c5705a77SAvi Kivity { 1858e1c57ab8SPaolo Bonzini RAMBlock *block; 18590d53d9feSMike Day RAMBlock *last_block = NULL; 18602152f5caSJuan Quintela ram_addr_t old_ram_size, new_ram_size; 186137aa7a0eSMarkus Armbruster Error *err = NULL; 18622152f5caSJuan Quintela 1863b8c48993SJuan Quintela old_ram_size = last_ram_page(); 1864c5705a77SAvi Kivity 1865b2a8658eSUmesh Deshpande qemu_mutex_lock_ramlist(); 18669b8424d5SMichael S. Tsirkin new_block->offset = find_ram_offset(new_block->max_length); 1867e1c57ab8SPaolo Bonzini 18680628c182SMarkus Armbruster if (!new_block->host) { 1869e1c57ab8SPaolo Bonzini if (xen_enabled()) { 18709b8424d5SMichael S. Tsirkin xen_ram_alloc(new_block->offset, new_block->max_length, 187137aa7a0eSMarkus Armbruster new_block->mr, &err); 187237aa7a0eSMarkus Armbruster if (err) { 187337aa7a0eSMarkus Armbruster error_propagate(errp, err); 187437aa7a0eSMarkus Armbruster qemu_mutex_unlock_ramlist(); 187539c350eeSPaolo Bonzini return; 187637aa7a0eSMarkus Armbruster } 1877e1c57ab8SPaolo Bonzini } else { 18789b8424d5SMichael S. Tsirkin new_block->host = phys_mem_alloc(new_block->max_length, 1879a2b257d6SIgor Mammedov &new_block->mr->align); 188039228250SMarkus Armbruster if (!new_block->host) { 1881ef701d7bSHu Tao error_setg_errno(errp, errno, 1882ef701d7bSHu Tao "cannot set up guest memory '%s'", 1883ef701d7bSHu Tao memory_region_name(new_block->mr)); 1884ef701d7bSHu Tao qemu_mutex_unlock_ramlist(); 188539c350eeSPaolo Bonzini return; 188639228250SMarkus Armbruster } 18879b8424d5SMichael S. Tsirkin memory_try_enable_merging(new_block->host, new_block->max_length); 1888c902760fSMarcelo Tosatti } 18896977dfe6SYoshiaki Tamura } 189094a6b54fSpbrook 1891dd631697SLi Zhijian new_ram_size = MAX(old_ram_size, 1892dd631697SLi Zhijian (new_block->offset + new_block->max_length) >> TARGET_PAGE_BITS); 1893dd631697SLi Zhijian if (new_ram_size > old_ram_size) { 18945b82b703SStefan Hajnoczi dirty_memory_extend(old_ram_size, new_ram_size); 1895dd631697SLi Zhijian } 18960d53d9feSMike Day /* Keep the list sorted from biggest to smallest block. Unlike QTAILQ, 18970d53d9feSMike Day * QLIST (which has an RCU-friendly variant) does not have insertion at 18980d53d9feSMike Day * tail, so save the last element in last_block. 18990d53d9feSMike Day */ 190099e15582SPeter Xu RAMBLOCK_FOREACH(block) { 19010d53d9feSMike Day last_block = block; 19029b8424d5SMichael S. Tsirkin if (block->max_length < new_block->max_length) { 1903abb26d63SPaolo Bonzini break; 1904abb26d63SPaolo Bonzini } 1905abb26d63SPaolo Bonzini } 1906abb26d63SPaolo Bonzini if (block) { 19070dc3f44aSMike Day QLIST_INSERT_BEFORE_RCU(block, new_block, next); 19080d53d9feSMike Day } else if (last_block) { 19090dc3f44aSMike Day QLIST_INSERT_AFTER_RCU(last_block, new_block, next); 19100d53d9feSMike Day } else { /* list is empty */ 19110dc3f44aSMike Day QLIST_INSERT_HEAD_RCU(&ram_list.blocks, new_block, next); 1912abb26d63SPaolo Bonzini } 19130d6d3c87SPaolo Bonzini ram_list.mru_block = NULL; 191494a6b54fSpbrook 19150dc3f44aSMike Day /* Write list before version */ 19160dc3f44aSMike Day smp_wmb(); 1917f798b07fSUmesh Deshpande ram_list.version++; 1918b2a8658eSUmesh Deshpande qemu_mutex_unlock_ramlist(); 1919f798b07fSUmesh Deshpande 19209b8424d5SMichael S. Tsirkin cpu_physical_memory_set_dirty_range(new_block->offset, 192158d2707eSPaolo Bonzini new_block->used_length, 192258d2707eSPaolo Bonzini DIRTY_CLIENTS_ALL); 192394a6b54fSpbrook 1924a904c911SPaolo Bonzini if (new_block->host) { 19259b8424d5SMichael S. Tsirkin qemu_ram_setup_dump(new_block->host, new_block->max_length); 19269b8424d5SMichael S. Tsirkin qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_HUGEPAGE); 1927c2cd627dSCao jin /* MADV_DONTFORK is also needed by KVM in absence of synchronous MMU */ 19289b8424d5SMichael S. Tsirkin qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_DONTFORK); 19290987d735SPaolo Bonzini ram_block_notify_add(new_block->host, new_block->max_length); 1930a904c911SPaolo Bonzini } 193194a6b54fSpbrook } 1932e9a1ab19Sbellard 19330b183fc8SPaolo Bonzini #ifdef __linux__ 1934528f46afSFam Zheng RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, 1935dbcb8981SPaolo Bonzini bool share, const char *mem_path, 19367f56e740SPaolo Bonzini Error **errp) 1937e1c57ab8SPaolo Bonzini { 1938e1c57ab8SPaolo Bonzini RAMBlock *new_block; 1939ef701d7bSHu Tao Error *local_err = NULL; 1940e1c57ab8SPaolo Bonzini 1941e1c57ab8SPaolo Bonzini if (xen_enabled()) { 19427f56e740SPaolo Bonzini error_setg(errp, "-mem-path not supported with Xen"); 1943528f46afSFam Zheng return NULL; 1944e1c57ab8SPaolo Bonzini } 1945e1c57ab8SPaolo Bonzini 1946e1c57ab8SPaolo Bonzini if (phys_mem_alloc != qemu_anon_ram_alloc) { 1947e1c57ab8SPaolo Bonzini /* 1948e1c57ab8SPaolo Bonzini * file_ram_alloc() needs to allocate just like 1949e1c57ab8SPaolo Bonzini * phys_mem_alloc, but we haven't bothered to provide 1950e1c57ab8SPaolo Bonzini * a hook there. 1951e1c57ab8SPaolo Bonzini */ 19527f56e740SPaolo Bonzini error_setg(errp, 19537f56e740SPaolo Bonzini "-mem-path not supported with this accelerator"); 1954528f46afSFam Zheng return NULL; 1955e1c57ab8SPaolo Bonzini } 1956e1c57ab8SPaolo Bonzini 19574ed023ceSDr. David Alan Gilbert size = HOST_PAGE_ALIGN(size); 1958e1c57ab8SPaolo Bonzini new_block = g_malloc0(sizeof(*new_block)); 1959e1c57ab8SPaolo Bonzini new_block->mr = mr; 19609b8424d5SMichael S. Tsirkin new_block->used_length = size; 19619b8424d5SMichael S. Tsirkin new_block->max_length = size; 1962dbcb8981SPaolo Bonzini new_block->flags = share ? RAM_SHARED : 0; 19637f56e740SPaolo Bonzini new_block->host = file_ram_alloc(new_block, size, 19647f56e740SPaolo Bonzini mem_path, errp); 19657f56e740SPaolo Bonzini if (!new_block->host) { 19667f56e740SPaolo Bonzini g_free(new_block); 1967528f46afSFam Zheng return NULL; 19687f56e740SPaolo Bonzini } 19697f56e740SPaolo Bonzini 1970528f46afSFam Zheng ram_block_add(new_block, &local_err); 1971ef701d7bSHu Tao if (local_err) { 1972ef701d7bSHu Tao g_free(new_block); 1973ef701d7bSHu Tao error_propagate(errp, local_err); 1974528f46afSFam Zheng return NULL; 1975ef701d7bSHu Tao } 1976528f46afSFam Zheng return new_block; 1977e1c57ab8SPaolo Bonzini } 19780b183fc8SPaolo Bonzini #endif 1979e1c57ab8SPaolo Bonzini 198062be4e3aSMichael S. Tsirkin static 1981528f46afSFam Zheng RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size, 198262be4e3aSMichael S. Tsirkin void (*resized)(const char*, 198362be4e3aSMichael S. Tsirkin uint64_t length, 198462be4e3aSMichael S. Tsirkin void *host), 198562be4e3aSMichael S. Tsirkin void *host, bool resizeable, 1986ef701d7bSHu Tao MemoryRegion *mr, Error **errp) 1987e1c57ab8SPaolo Bonzini { 1988e1c57ab8SPaolo Bonzini RAMBlock *new_block; 1989ef701d7bSHu Tao Error *local_err = NULL; 1990e1c57ab8SPaolo Bonzini 19914ed023ceSDr. David Alan Gilbert size = HOST_PAGE_ALIGN(size); 19924ed023ceSDr. David Alan Gilbert max_size = HOST_PAGE_ALIGN(max_size); 1993e1c57ab8SPaolo Bonzini new_block = g_malloc0(sizeof(*new_block)); 1994e1c57ab8SPaolo Bonzini new_block->mr = mr; 199562be4e3aSMichael S. Tsirkin new_block->resized = resized; 19969b8424d5SMichael S. Tsirkin new_block->used_length = size; 19979b8424d5SMichael S. Tsirkin new_block->max_length = max_size; 199862be4e3aSMichael S. Tsirkin assert(max_size >= size); 1999e1c57ab8SPaolo Bonzini new_block->fd = -1; 2000863e9621SDr. David Alan Gilbert new_block->page_size = getpagesize(); 2001e1c57ab8SPaolo Bonzini new_block->host = host; 2002e1c57ab8SPaolo Bonzini if (host) { 20037bd4f430SPaolo Bonzini new_block->flags |= RAM_PREALLOC; 2004e1c57ab8SPaolo Bonzini } 200562be4e3aSMichael S. Tsirkin if (resizeable) { 200662be4e3aSMichael S. Tsirkin new_block->flags |= RAM_RESIZEABLE; 200762be4e3aSMichael S. Tsirkin } 2008528f46afSFam Zheng ram_block_add(new_block, &local_err); 2009ef701d7bSHu Tao if (local_err) { 2010ef701d7bSHu Tao g_free(new_block); 2011ef701d7bSHu Tao error_propagate(errp, local_err); 2012528f46afSFam Zheng return NULL; 2013ef701d7bSHu Tao } 2014528f46afSFam Zheng return new_block; 2015e1c57ab8SPaolo Bonzini } 2016e1c57ab8SPaolo Bonzini 2017528f46afSFam Zheng RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, 201862be4e3aSMichael S. Tsirkin MemoryRegion *mr, Error **errp) 201962be4e3aSMichael S. Tsirkin { 202062be4e3aSMichael S. Tsirkin return qemu_ram_alloc_internal(size, size, NULL, host, false, mr, errp); 202162be4e3aSMichael S. Tsirkin } 202262be4e3aSMichael S. Tsirkin 2023528f46afSFam Zheng RAMBlock *qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr, Error **errp) 20246977dfe6SYoshiaki Tamura { 202562be4e3aSMichael S. Tsirkin return qemu_ram_alloc_internal(size, size, NULL, NULL, false, mr, errp); 202662be4e3aSMichael S. Tsirkin } 202762be4e3aSMichael S. Tsirkin 2028528f46afSFam Zheng RAMBlock *qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t maxsz, 202962be4e3aSMichael S. Tsirkin void (*resized)(const char*, 203062be4e3aSMichael S. Tsirkin uint64_t length, 203162be4e3aSMichael S. Tsirkin void *host), 203262be4e3aSMichael S. Tsirkin MemoryRegion *mr, Error **errp) 203362be4e3aSMichael S. Tsirkin { 203462be4e3aSMichael S. Tsirkin return qemu_ram_alloc_internal(size, maxsz, resized, NULL, true, mr, errp); 20356977dfe6SYoshiaki Tamura } 20366977dfe6SYoshiaki Tamura 203743771539SPaolo Bonzini static void reclaim_ramblock(RAMBlock *block) 2038e9a1ab19Sbellard { 20397bd4f430SPaolo Bonzini if (block->flags & RAM_PREALLOC) { 2040cd19cfa2SHuang Ying ; 2041dfeaf2abSMarkus Armbruster } else if (xen_enabled()) { 2042dfeaf2abSMarkus Armbruster xen_invalidate_map_cache_entry(block->host); 2043089f3f76SStefan Weil #ifndef _WIN32 20443435f395SMarkus Armbruster } else if (block->fd >= 0) { 2045794e8f30SMichael S. Tsirkin qemu_ram_munmap(block->host, block->max_length); 204604b16653SAlex Williamson close(block->fd); 2047089f3f76SStefan Weil #endif 204804b16653SAlex Williamson } else { 20499b8424d5SMichael S. Tsirkin qemu_anon_ram_free(block->host, block->max_length); 205004b16653SAlex Williamson } 20517267c094SAnthony Liguori g_free(block); 205243771539SPaolo Bonzini } 205343771539SPaolo Bonzini 2054f1060c55SFam Zheng void qemu_ram_free(RAMBlock *block) 205543771539SPaolo Bonzini { 205685bc2a15SMarc-André Lureau if (!block) { 205785bc2a15SMarc-André Lureau return; 205885bc2a15SMarc-André Lureau } 205985bc2a15SMarc-André Lureau 20600987d735SPaolo Bonzini if (block->host) { 20610987d735SPaolo Bonzini ram_block_notify_remove(block->host, block->max_length); 20620987d735SPaolo Bonzini } 20630987d735SPaolo Bonzini 206443771539SPaolo Bonzini qemu_mutex_lock_ramlist(); 20650dc3f44aSMike Day QLIST_REMOVE_RCU(block, next); 206643771539SPaolo Bonzini ram_list.mru_block = NULL; 20670dc3f44aSMike Day /* Write list before version */ 20680dc3f44aSMike Day smp_wmb(); 206943771539SPaolo Bonzini ram_list.version++; 207043771539SPaolo Bonzini call_rcu(block, reclaim_ramblock, rcu); 2071b2a8658eSUmesh Deshpande qemu_mutex_unlock_ramlist(); 2072e9a1ab19Sbellard } 2073e9a1ab19Sbellard 2074cd19cfa2SHuang Ying #ifndef _WIN32 2075cd19cfa2SHuang Ying void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) 2076cd19cfa2SHuang Ying { 2077cd19cfa2SHuang Ying RAMBlock *block; 2078cd19cfa2SHuang Ying ram_addr_t offset; 2079cd19cfa2SHuang Ying int flags; 2080cd19cfa2SHuang Ying void *area, *vaddr; 2081cd19cfa2SHuang Ying 208299e15582SPeter Xu RAMBLOCK_FOREACH(block) { 2083cd19cfa2SHuang Ying offset = addr - block->offset; 20849b8424d5SMichael S. Tsirkin if (offset < block->max_length) { 20851240be24SMichael S. Tsirkin vaddr = ramblock_ptr(block, offset); 20867bd4f430SPaolo Bonzini if (block->flags & RAM_PREALLOC) { 2087cd19cfa2SHuang Ying ; 2088dfeaf2abSMarkus Armbruster } else if (xen_enabled()) { 2089dfeaf2abSMarkus Armbruster abort(); 2090cd19cfa2SHuang Ying } else { 2091cd19cfa2SHuang Ying flags = MAP_FIXED; 20923435f395SMarkus Armbruster if (block->fd >= 0) { 2093dbcb8981SPaolo Bonzini flags |= (block->flags & RAM_SHARED ? 2094dbcb8981SPaolo Bonzini MAP_SHARED : MAP_PRIVATE); 2095cd19cfa2SHuang Ying area = mmap(vaddr, length, PROT_READ | PROT_WRITE, 2096cd19cfa2SHuang Ying flags, block->fd, offset); 2097cd19cfa2SHuang Ying } else { 20982eb9fbaaSMarkus Armbruster /* 20992eb9fbaaSMarkus Armbruster * Remap needs to match alloc. Accelerators that 21002eb9fbaaSMarkus Armbruster * set phys_mem_alloc never remap. If they did, 21012eb9fbaaSMarkus Armbruster * we'd need a remap hook here. 21022eb9fbaaSMarkus Armbruster */ 21032eb9fbaaSMarkus Armbruster assert(phys_mem_alloc == qemu_anon_ram_alloc); 21042eb9fbaaSMarkus Armbruster 2105cd19cfa2SHuang Ying flags |= MAP_PRIVATE | MAP_ANONYMOUS; 2106cd19cfa2SHuang Ying area = mmap(vaddr, length, PROT_READ | PROT_WRITE, 2107cd19cfa2SHuang Ying flags, -1, 0); 2108cd19cfa2SHuang Ying } 2109cd19cfa2SHuang Ying if (area != vaddr) { 2110f15fbc4bSAnthony PERARD fprintf(stderr, "Could not remap addr: " 2111f15fbc4bSAnthony PERARD RAM_ADDR_FMT "@" RAM_ADDR_FMT "\n", 2112cd19cfa2SHuang Ying length, addr); 2113cd19cfa2SHuang Ying exit(1); 2114cd19cfa2SHuang Ying } 21158490fc78SLuiz Capitulino memory_try_enable_merging(vaddr, length); 2116ddb97f1dSJason Baron qemu_ram_setup_dump(vaddr, length); 2117cd19cfa2SHuang Ying } 2118cd19cfa2SHuang Ying } 2119cd19cfa2SHuang Ying } 2120cd19cfa2SHuang Ying } 2121cd19cfa2SHuang Ying #endif /* !_WIN32 */ 2122cd19cfa2SHuang Ying 21231b5ec234SPaolo Bonzini /* Return a host pointer to ram allocated with qemu_ram_alloc. 2124ae3a7047SMike Day * This should not be used for general purpose DMA. Use address_space_map 2125ae3a7047SMike Day * or address_space_rw instead. For local memory (e.g. video ram) that the 2126ae3a7047SMike Day * device owns, use memory_region_get_ram_ptr. 21270dc3f44aSMike Day * 212849b24afcSPaolo Bonzini * Called within RCU critical section. 21291b5ec234SPaolo Bonzini */ 21300878d0e1SPaolo Bonzini void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr) 21311b5ec234SPaolo Bonzini { 21323655cb9cSGonglei RAMBlock *block = ram_block; 21333655cb9cSGonglei 21343655cb9cSGonglei if (block == NULL) { 21353655cb9cSGonglei block = qemu_get_ram_block(addr); 21360878d0e1SPaolo Bonzini addr -= block->offset; 21373655cb9cSGonglei } 2138ae3a7047SMike Day 2139ae3a7047SMike Day if (xen_enabled() && block->host == NULL) { 2140432d268cSJun Nakajima /* We need to check if the requested address is in the RAM 2141432d268cSJun Nakajima * because we don't want to map the entire memory in QEMU. 2142712c2b41SStefano Stabellini * In that case just map until the end of the page. 2143432d268cSJun Nakajima */ 2144432d268cSJun Nakajima if (block->offset == 0) { 21451ff7c598SStefano Stabellini return xen_map_cache(addr, 0, 0, false); 2146432d268cSJun Nakajima } 2147ae3a7047SMike Day 21481ff7c598SStefano Stabellini block->host = xen_map_cache(block->offset, block->max_length, 1, false); 2149432d268cSJun Nakajima } 21500878d0e1SPaolo Bonzini return ramblock_ptr(block, addr); 215194a6b54fSpbrook } 2152f471a17eSAlex Williamson 21530878d0e1SPaolo Bonzini /* Return a host pointer to guest's ram. Similar to qemu_map_ram_ptr 2154ae3a7047SMike Day * but takes a size argument. 21550dc3f44aSMike Day * 2156e81bcda5SPaolo Bonzini * Called within RCU critical section. 2157ae3a7047SMike Day */ 21583655cb9cSGonglei static void *qemu_ram_ptr_length(RAMBlock *ram_block, ram_addr_t addr, 21593655cb9cSGonglei hwaddr *size) 216038bee5dcSStefano Stabellini { 21613655cb9cSGonglei RAMBlock *block = ram_block; 21628ab934f9SStefano Stabellini if (*size == 0) { 21638ab934f9SStefano Stabellini return NULL; 21648ab934f9SStefano Stabellini } 2165e81bcda5SPaolo Bonzini 21663655cb9cSGonglei if (block == NULL) { 2167e81bcda5SPaolo Bonzini block = qemu_get_ram_block(addr); 21680878d0e1SPaolo Bonzini addr -= block->offset; 21693655cb9cSGonglei } 21700878d0e1SPaolo Bonzini *size = MIN(*size, block->max_length - addr); 2171e81bcda5SPaolo Bonzini 2172e81bcda5SPaolo Bonzini if (xen_enabled() && block->host == NULL) { 2173e81bcda5SPaolo Bonzini /* We need to check if the requested address is in the RAM 2174e81bcda5SPaolo Bonzini * because we don't want to map the entire memory in QEMU. 2175e81bcda5SPaolo Bonzini * In that case just map the requested area. 2176e81bcda5SPaolo Bonzini */ 2177e81bcda5SPaolo Bonzini if (block->offset == 0) { 21781ff7c598SStefano Stabellini return xen_map_cache(addr, *size, 1, true); 217938bee5dcSStefano Stabellini } 218038bee5dcSStefano Stabellini 21811ff7c598SStefano Stabellini block->host = xen_map_cache(block->offset, block->max_length, 1, true); 218238bee5dcSStefano Stabellini } 2183e81bcda5SPaolo Bonzini 21840878d0e1SPaolo Bonzini return ramblock_ptr(block, addr); 218538bee5dcSStefano Stabellini } 218638bee5dcSStefano Stabellini 2187422148d3SDr. David Alan Gilbert /* 2188422148d3SDr. David Alan Gilbert * Translates a host ptr back to a RAMBlock, a ram_addr and an offset 2189422148d3SDr. David Alan Gilbert * in that RAMBlock. 2190422148d3SDr. David Alan Gilbert * 2191422148d3SDr. David Alan Gilbert * ptr: Host pointer to look up 2192422148d3SDr. David Alan Gilbert * round_offset: If true round the result offset down to a page boundary 2193422148d3SDr. David Alan Gilbert * *ram_addr: set to result ram_addr 2194422148d3SDr. David Alan Gilbert * *offset: set to result offset within the RAMBlock 2195422148d3SDr. David Alan Gilbert * 2196422148d3SDr. David Alan Gilbert * Returns: RAMBlock (or NULL if not found) 2197ae3a7047SMike Day * 2198ae3a7047SMike Day * By the time this function returns, the returned pointer is not protected 2199ae3a7047SMike Day * by RCU anymore. If the caller is not within an RCU critical section and 2200ae3a7047SMike Day * does not hold the iothread lock, it must have other means of protecting the 2201ae3a7047SMike Day * pointer, such as a reference to the region that includes the incoming 2202ae3a7047SMike Day * ram_addr_t. 2203ae3a7047SMike Day */ 2204422148d3SDr. David Alan Gilbert RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset, 2205422148d3SDr. David Alan Gilbert ram_addr_t *offset) 22065579c7f3Spbrook { 220794a6b54fSpbrook RAMBlock *block; 220894a6b54fSpbrook uint8_t *host = ptr; 220994a6b54fSpbrook 2210868bb33fSJan Kiszka if (xen_enabled()) { 2211f615f396SPaolo Bonzini ram_addr_t ram_addr; 22120dc3f44aSMike Day rcu_read_lock(); 2213f615f396SPaolo Bonzini ram_addr = xen_ram_addr_from_mapcache(ptr); 2214f615f396SPaolo Bonzini block = qemu_get_ram_block(ram_addr); 2215422148d3SDr. David Alan Gilbert if (block) { 2216d6b6aec4SAnthony PERARD *offset = ram_addr - block->offset; 2217422148d3SDr. David Alan Gilbert } 22180dc3f44aSMike Day rcu_read_unlock(); 2219422148d3SDr. David Alan Gilbert return block; 2220712c2b41SStefano Stabellini } 2221712c2b41SStefano Stabellini 22220dc3f44aSMike Day rcu_read_lock(); 22230dc3f44aSMike Day block = atomic_rcu_read(&ram_list.mru_block); 22249b8424d5SMichael S. Tsirkin if (block && block->host && host - block->host < block->max_length) { 222523887b79SPaolo Bonzini goto found; 222623887b79SPaolo Bonzini } 222723887b79SPaolo Bonzini 222899e15582SPeter Xu RAMBLOCK_FOREACH(block) { 2229432d268cSJun Nakajima /* This case append when the block is not mapped. */ 2230432d268cSJun Nakajima if (block->host == NULL) { 2231432d268cSJun Nakajima continue; 2232432d268cSJun Nakajima } 22339b8424d5SMichael S. Tsirkin if (host - block->host < block->max_length) { 223423887b79SPaolo Bonzini goto found; 223594a6b54fSpbrook } 2236f471a17eSAlex Williamson } 2237432d268cSJun Nakajima 22380dc3f44aSMike Day rcu_read_unlock(); 22391b5ec234SPaolo Bonzini return NULL; 224023887b79SPaolo Bonzini 224123887b79SPaolo Bonzini found: 2242422148d3SDr. David Alan Gilbert *offset = (host - block->host); 2243422148d3SDr. David Alan Gilbert if (round_offset) { 2244422148d3SDr. David Alan Gilbert *offset &= TARGET_PAGE_MASK; 2245422148d3SDr. David Alan Gilbert } 22460dc3f44aSMike Day rcu_read_unlock(); 2247422148d3SDr. David Alan Gilbert return block; 2248422148d3SDr. David Alan Gilbert } 2249422148d3SDr. David Alan Gilbert 2250e3dd7493SDr. David Alan Gilbert /* 2251e3dd7493SDr. David Alan Gilbert * Finds the named RAMBlock 2252e3dd7493SDr. David Alan Gilbert * 2253e3dd7493SDr. David Alan Gilbert * name: The name of RAMBlock to find 2254e3dd7493SDr. David Alan Gilbert * 2255e3dd7493SDr. David Alan Gilbert * Returns: RAMBlock (or NULL if not found) 2256e3dd7493SDr. David Alan Gilbert */ 2257e3dd7493SDr. David Alan Gilbert RAMBlock *qemu_ram_block_by_name(const char *name) 2258e3dd7493SDr. David Alan Gilbert { 2259e3dd7493SDr. David Alan Gilbert RAMBlock *block; 2260e3dd7493SDr. David Alan Gilbert 226199e15582SPeter Xu RAMBLOCK_FOREACH(block) { 2262e3dd7493SDr. David Alan Gilbert if (!strcmp(name, block->idstr)) { 2263e3dd7493SDr. David Alan Gilbert return block; 2264e3dd7493SDr. David Alan Gilbert } 2265e3dd7493SDr. David Alan Gilbert } 2266e3dd7493SDr. David Alan Gilbert 2267e3dd7493SDr. David Alan Gilbert return NULL; 2268e3dd7493SDr. David Alan Gilbert } 2269e3dd7493SDr. David Alan Gilbert 2270422148d3SDr. David Alan Gilbert /* Some of the softmmu routines need to translate from a host pointer 2271422148d3SDr. David Alan Gilbert (typically a TLB entry) back to a ram offset. */ 227207bdaa41SPaolo Bonzini ram_addr_t qemu_ram_addr_from_host(void *ptr) 2273422148d3SDr. David Alan Gilbert { 2274422148d3SDr. David Alan Gilbert RAMBlock *block; 2275f615f396SPaolo Bonzini ram_addr_t offset; 2276422148d3SDr. David Alan Gilbert 2277f615f396SPaolo Bonzini block = qemu_ram_block_from_host(ptr, false, &offset); 2278422148d3SDr. David Alan Gilbert if (!block) { 227907bdaa41SPaolo Bonzini return RAM_ADDR_INVALID; 2280422148d3SDr. David Alan Gilbert } 2281422148d3SDr. David Alan Gilbert 228207bdaa41SPaolo Bonzini return block->offset + offset; 2283e890261fSMarcelo Tosatti } 2284f471a17eSAlex Williamson 228549b24afcSPaolo Bonzini /* Called within RCU critical section. */ 2286a8170e5eSAvi Kivity static void notdirty_mem_write(void *opaque, hwaddr ram_addr, 22870e0df1e2SAvi Kivity uint64_t val, unsigned size) 22881ccde1cbSbellard { 2289ba051fb5SAlex Bennée bool locked = false; 2290ba051fb5SAlex Bennée 229152159192SJuan Quintela if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) { 2292ba051fb5SAlex Bennée locked = true; 2293ba051fb5SAlex Bennée tb_lock(); 22940e0df1e2SAvi Kivity tb_invalidate_phys_page_fast(ram_addr, size); 22953a7d929eSbellard } 22960e0df1e2SAvi Kivity switch (size) { 22970e0df1e2SAvi Kivity case 1: 22980878d0e1SPaolo Bonzini stb_p(qemu_map_ram_ptr(NULL, ram_addr), val); 22990e0df1e2SAvi Kivity break; 23000e0df1e2SAvi Kivity case 2: 23010878d0e1SPaolo Bonzini stw_p(qemu_map_ram_ptr(NULL, ram_addr), val); 23020e0df1e2SAvi Kivity break; 23030e0df1e2SAvi Kivity case 4: 23040878d0e1SPaolo Bonzini stl_p(qemu_map_ram_ptr(NULL, ram_addr), val); 23050e0df1e2SAvi Kivity break; 23060e0df1e2SAvi Kivity default: 23070e0df1e2SAvi Kivity abort(); 23080e0df1e2SAvi Kivity } 2309ba051fb5SAlex Bennée 2310ba051fb5SAlex Bennée if (locked) { 2311ba051fb5SAlex Bennée tb_unlock(); 2312ba051fb5SAlex Bennée } 2313ba051fb5SAlex Bennée 231458d2707eSPaolo Bonzini /* Set both VGA and migration bits for simplicity and to remove 231558d2707eSPaolo Bonzini * the notdirty callback faster. 231658d2707eSPaolo Bonzini */ 231758d2707eSPaolo Bonzini cpu_physical_memory_set_dirty_range(ram_addr, size, 231858d2707eSPaolo Bonzini DIRTY_CLIENTS_NOCODE); 2319f23db169Sbellard /* we remove the notdirty callback only if the code has been 2320f23db169Sbellard flushed */ 2321a2cd8c85SJuan Quintela if (!cpu_physical_memory_is_clean(ram_addr)) { 2322bcae01e4SPeter Crosthwaite tlb_set_dirty(current_cpu, current_cpu->mem_io_vaddr); 23234917cf44SAndreas Färber } 23241ccde1cbSbellard } 23251ccde1cbSbellard 2326b018ddf6SPaolo Bonzini static bool notdirty_mem_accepts(void *opaque, hwaddr addr, 2327b018ddf6SPaolo Bonzini unsigned size, bool is_write) 2328b018ddf6SPaolo Bonzini { 2329b018ddf6SPaolo Bonzini return is_write; 2330b018ddf6SPaolo Bonzini } 2331b018ddf6SPaolo Bonzini 23320e0df1e2SAvi Kivity static const MemoryRegionOps notdirty_mem_ops = { 23330e0df1e2SAvi Kivity .write = notdirty_mem_write, 2334b018ddf6SPaolo Bonzini .valid.accepts = notdirty_mem_accepts, 23350e0df1e2SAvi Kivity .endianness = DEVICE_NATIVE_ENDIAN, 23361ccde1cbSbellard }; 23371ccde1cbSbellard 23380f459d16Spbrook /* Generate a debug exception if a watchpoint has been hit. */ 233966b9b43cSPeter Maydell static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags) 23400f459d16Spbrook { 234193afeadeSAndreas Färber CPUState *cpu = current_cpu; 2342568496c0SSergey Fedorov CPUClass *cc = CPU_GET_CLASS(cpu); 234393afeadeSAndreas Färber CPUArchState *env = cpu->env_ptr; 234406d55cc1Saliguori target_ulong pc, cs_base; 23450f459d16Spbrook target_ulong vaddr; 2346a1d1bb31Saliguori CPUWatchpoint *wp; 234789fee74aSEmilio G. Cota uint32_t cpu_flags; 23480f459d16Spbrook 2349ff4700b0SAndreas Färber if (cpu->watchpoint_hit) { 235006d55cc1Saliguori /* We re-entered the check after replacing the TB. Now raise 235106d55cc1Saliguori * the debug interrupt so that is will trigger after the 235206d55cc1Saliguori * current instruction. */ 235393afeadeSAndreas Färber cpu_interrupt(cpu, CPU_INTERRUPT_DEBUG); 235406d55cc1Saliguori return; 235506d55cc1Saliguori } 235693afeadeSAndreas Färber vaddr = (cpu->mem_io_vaddr & TARGET_PAGE_MASK) + offset; 235740612000SJulian Brown vaddr = cc->adjust_watchpoint_address(cpu, vaddr, len); 2358ff4700b0SAndreas Färber QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { 235905068c0dSPeter Maydell if (cpu_watchpoint_address_matches(wp, vaddr, len) 236005068c0dSPeter Maydell && (wp->flags & flags)) { 236108225676SPeter Maydell if (flags == BP_MEM_READ) { 236208225676SPeter Maydell wp->flags |= BP_WATCHPOINT_HIT_READ; 236308225676SPeter Maydell } else { 236408225676SPeter Maydell wp->flags |= BP_WATCHPOINT_HIT_WRITE; 236508225676SPeter Maydell } 236608225676SPeter Maydell wp->hitaddr = vaddr; 236766b9b43cSPeter Maydell wp->hitattrs = attrs; 2368ff4700b0SAndreas Färber if (!cpu->watchpoint_hit) { 2369568496c0SSergey Fedorov if (wp->flags & BP_CPU && 2370568496c0SSergey Fedorov !cc->debug_check_watchpoint(cpu, wp)) { 2371568496c0SSergey Fedorov wp->flags &= ~BP_WATCHPOINT_HIT; 2372568496c0SSergey Fedorov continue; 2373568496c0SSergey Fedorov } 2374ff4700b0SAndreas Färber cpu->watchpoint_hit = wp; 2375a5e99826SKONRAD Frederic 23768d04fb55SJan Kiszka /* Both tb_lock and iothread_mutex will be reset when 23778d04fb55SJan Kiszka * cpu_loop_exit or cpu_loop_exit_noexc longjmp 23788d04fb55SJan Kiszka * back into the cpu_exec main loop. 2379a5e99826SKONRAD Frederic */ 2380a5e99826SKONRAD Frederic tb_lock(); 2381239c51a5SAndreas Färber tb_check_watchpoint(cpu); 238206d55cc1Saliguori if (wp->flags & BP_STOP_BEFORE_ACCESS) { 238327103424SAndreas Färber cpu->exception_index = EXCP_DEBUG; 23845638d180SAndreas Färber cpu_loop_exit(cpu); 238506d55cc1Saliguori } else { 238606d55cc1Saliguori cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags); 2387648f034cSAndreas Färber tb_gen_code(cpu, pc, cs_base, cpu_flags, 1); 23886886b980SPeter Maydell cpu_loop_exit_noexc(cpu); 23890f459d16Spbrook } 2390488d6577SMax Filippov } 23916e140f28Saliguori } else { 23926e140f28Saliguori wp->flags &= ~BP_WATCHPOINT_HIT; 23936e140f28Saliguori } 23940f459d16Spbrook } 23950f459d16Spbrook } 23960f459d16Spbrook 23976658ffb8Spbrook /* Watchpoint access routines. Watchpoints are inserted using TLB tricks, 23986658ffb8Spbrook so these check for a hit then pass through to the normal out-of-line 23996658ffb8Spbrook phys routines. */ 240066b9b43cSPeter Maydell static MemTxResult watch_mem_read(void *opaque, hwaddr addr, uint64_t *pdata, 240166b9b43cSPeter Maydell unsigned size, MemTxAttrs attrs) 24026658ffb8Spbrook { 240366b9b43cSPeter Maydell MemTxResult res; 240466b9b43cSPeter Maydell uint64_t data; 240579ed0416SPeter Maydell int asidx = cpu_asidx_from_attrs(current_cpu, attrs); 240679ed0416SPeter Maydell AddressSpace *as = current_cpu->cpu_ases[asidx].as; 24076658ffb8Spbrook 240866b9b43cSPeter Maydell check_watchpoint(addr & ~TARGET_PAGE_MASK, size, attrs, BP_MEM_READ); 24091ec9b909SAvi Kivity switch (size) { 241067364150SMax Filippov case 1: 241179ed0416SPeter Maydell data = address_space_ldub(as, addr, attrs, &res); 241267364150SMax Filippov break; 241367364150SMax Filippov case 2: 241479ed0416SPeter Maydell data = address_space_lduw(as, addr, attrs, &res); 241567364150SMax Filippov break; 241667364150SMax Filippov case 4: 241779ed0416SPeter Maydell data = address_space_ldl(as, addr, attrs, &res); 241867364150SMax Filippov break; 24191ec9b909SAvi Kivity default: abort(); 24201ec9b909SAvi Kivity } 242166b9b43cSPeter Maydell *pdata = data; 242266b9b43cSPeter Maydell return res; 242366b9b43cSPeter Maydell } 242466b9b43cSPeter Maydell 242566b9b43cSPeter Maydell static MemTxResult watch_mem_write(void *opaque, hwaddr addr, 242666b9b43cSPeter Maydell uint64_t val, unsigned size, 242766b9b43cSPeter Maydell MemTxAttrs attrs) 242866b9b43cSPeter Maydell { 242966b9b43cSPeter Maydell MemTxResult res; 243079ed0416SPeter Maydell int asidx = cpu_asidx_from_attrs(current_cpu, attrs); 243179ed0416SPeter Maydell AddressSpace *as = current_cpu->cpu_ases[asidx].as; 243266b9b43cSPeter Maydell 243366b9b43cSPeter Maydell check_watchpoint(addr & ~TARGET_PAGE_MASK, size, attrs, BP_MEM_WRITE); 243466b9b43cSPeter Maydell switch (size) { 243566b9b43cSPeter Maydell case 1: 243679ed0416SPeter Maydell address_space_stb(as, addr, val, attrs, &res); 243766b9b43cSPeter Maydell break; 243866b9b43cSPeter Maydell case 2: 243979ed0416SPeter Maydell address_space_stw(as, addr, val, attrs, &res); 244066b9b43cSPeter Maydell break; 244166b9b43cSPeter Maydell case 4: 244279ed0416SPeter Maydell address_space_stl(as, addr, val, attrs, &res); 244366b9b43cSPeter Maydell break; 244466b9b43cSPeter Maydell default: abort(); 244566b9b43cSPeter Maydell } 244666b9b43cSPeter Maydell return res; 24476658ffb8Spbrook } 24486658ffb8Spbrook 24491ec9b909SAvi Kivity static const MemoryRegionOps watch_mem_ops = { 245066b9b43cSPeter Maydell .read_with_attrs = watch_mem_read, 245166b9b43cSPeter Maydell .write_with_attrs = watch_mem_write, 24521ec9b909SAvi Kivity .endianness = DEVICE_NATIVE_ENDIAN, 24536658ffb8Spbrook }; 24546658ffb8Spbrook 2455f25a49e0SPeter Maydell static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data, 2456f25a49e0SPeter Maydell unsigned len, MemTxAttrs attrs) 2457db7b5426Sblueswir1 { 2458acc9d80bSJan Kiszka subpage_t *subpage = opaque; 2459ff6cff75SPaolo Bonzini uint8_t buf[8]; 24605c9eb028SPeter Maydell MemTxResult res; 2461791af8c8SPaolo Bonzini 2462db7b5426Sblueswir1 #if defined(DEBUG_SUBPAGE) 2463016e9d62SAmos Kong printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__, 2464acc9d80bSJan Kiszka subpage, len, addr); 2465db7b5426Sblueswir1 #endif 24665c9eb028SPeter Maydell res = address_space_read(subpage->as, addr + subpage->base, 24675c9eb028SPeter Maydell attrs, buf, len); 24685c9eb028SPeter Maydell if (res) { 24695c9eb028SPeter Maydell return res; 2470f25a49e0SPeter Maydell } 2471acc9d80bSJan Kiszka switch (len) { 2472acc9d80bSJan Kiszka case 1: 2473f25a49e0SPeter Maydell *data = ldub_p(buf); 2474f25a49e0SPeter Maydell return MEMTX_OK; 2475acc9d80bSJan Kiszka case 2: 2476f25a49e0SPeter Maydell *data = lduw_p(buf); 2477f25a49e0SPeter Maydell return MEMTX_OK; 2478acc9d80bSJan Kiszka case 4: 2479f25a49e0SPeter Maydell *data = ldl_p(buf); 2480f25a49e0SPeter Maydell return MEMTX_OK; 2481ff6cff75SPaolo Bonzini case 8: 2482f25a49e0SPeter Maydell *data = ldq_p(buf); 2483f25a49e0SPeter Maydell return MEMTX_OK; 2484acc9d80bSJan Kiszka default: 2485acc9d80bSJan Kiszka abort(); 2486acc9d80bSJan Kiszka } 2487db7b5426Sblueswir1 } 2488db7b5426Sblueswir1 2489f25a49e0SPeter Maydell static MemTxResult subpage_write(void *opaque, hwaddr addr, 2490f25a49e0SPeter Maydell uint64_t value, unsigned len, MemTxAttrs attrs) 2491db7b5426Sblueswir1 { 2492acc9d80bSJan Kiszka subpage_t *subpage = opaque; 2493ff6cff75SPaolo Bonzini uint8_t buf[8]; 2494acc9d80bSJan Kiszka 2495db7b5426Sblueswir1 #if defined(DEBUG_SUBPAGE) 2496016e9d62SAmos Kong printf("%s: subpage %p len %u addr " TARGET_FMT_plx 2497acc9d80bSJan Kiszka " value %"PRIx64"\n", 2498acc9d80bSJan Kiszka __func__, subpage, len, addr, value); 2499db7b5426Sblueswir1 #endif 2500acc9d80bSJan Kiszka switch (len) { 2501acc9d80bSJan Kiszka case 1: 2502acc9d80bSJan Kiszka stb_p(buf, value); 2503acc9d80bSJan Kiszka break; 2504acc9d80bSJan Kiszka case 2: 2505acc9d80bSJan Kiszka stw_p(buf, value); 2506acc9d80bSJan Kiszka break; 2507acc9d80bSJan Kiszka case 4: 2508acc9d80bSJan Kiszka stl_p(buf, value); 2509acc9d80bSJan Kiszka break; 2510ff6cff75SPaolo Bonzini case 8: 2511ff6cff75SPaolo Bonzini stq_p(buf, value); 2512ff6cff75SPaolo Bonzini break; 2513acc9d80bSJan Kiszka default: 2514acc9d80bSJan Kiszka abort(); 2515acc9d80bSJan Kiszka } 25165c9eb028SPeter Maydell return address_space_write(subpage->as, addr + subpage->base, 25175c9eb028SPeter Maydell attrs, buf, len); 2518db7b5426Sblueswir1 } 2519db7b5426Sblueswir1 2520c353e4ccSPaolo Bonzini static bool subpage_accepts(void *opaque, hwaddr addr, 2521016e9d62SAmos Kong unsigned len, bool is_write) 2522c353e4ccSPaolo Bonzini { 2523acc9d80bSJan Kiszka subpage_t *subpage = opaque; 2524c353e4ccSPaolo Bonzini #if defined(DEBUG_SUBPAGE) 2525016e9d62SAmos Kong printf("%s: subpage %p %c len %u addr " TARGET_FMT_plx "\n", 2526acc9d80bSJan Kiszka __func__, subpage, is_write ? 'w' : 'r', len, addr); 2527c353e4ccSPaolo Bonzini #endif 2528c353e4ccSPaolo Bonzini 2529acc9d80bSJan Kiszka return address_space_access_valid(subpage->as, addr + subpage->base, 2530016e9d62SAmos Kong len, is_write); 2531c353e4ccSPaolo Bonzini } 2532c353e4ccSPaolo Bonzini 253370c68e44SAvi Kivity static const MemoryRegionOps subpage_ops = { 2534f25a49e0SPeter Maydell .read_with_attrs = subpage_read, 2535f25a49e0SPeter Maydell .write_with_attrs = subpage_write, 2536ff6cff75SPaolo Bonzini .impl.min_access_size = 1, 2537ff6cff75SPaolo Bonzini .impl.max_access_size = 8, 2538ff6cff75SPaolo Bonzini .valid.min_access_size = 1, 2539ff6cff75SPaolo Bonzini .valid.max_access_size = 8, 2540c353e4ccSPaolo Bonzini .valid.accepts = subpage_accepts, 254170c68e44SAvi Kivity .endianness = DEVICE_NATIVE_ENDIAN, 2542db7b5426Sblueswir1 }; 2543db7b5426Sblueswir1 2544c227f099SAnthony Liguori static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, 25455312bd8bSAvi Kivity uint16_t section) 2546db7b5426Sblueswir1 { 2547db7b5426Sblueswir1 int idx, eidx; 2548db7b5426Sblueswir1 2549db7b5426Sblueswir1 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE) 2550db7b5426Sblueswir1 return -1; 2551db7b5426Sblueswir1 idx = SUBPAGE_IDX(start); 2552db7b5426Sblueswir1 eidx = SUBPAGE_IDX(end); 2553db7b5426Sblueswir1 #if defined(DEBUG_SUBPAGE) 2554016e9d62SAmos Kong printf("%s: %p start %08x end %08x idx %08x eidx %08x section %d\n", 2555016e9d62SAmos Kong __func__, mmio, start, end, idx, eidx, section); 2556db7b5426Sblueswir1 #endif 2557db7b5426Sblueswir1 for (; idx <= eidx; idx++) { 25585312bd8bSAvi Kivity mmio->sub_section[idx] = section; 2559db7b5426Sblueswir1 } 2560db7b5426Sblueswir1 2561db7b5426Sblueswir1 return 0; 2562db7b5426Sblueswir1 } 2563db7b5426Sblueswir1 2564acc9d80bSJan Kiszka static subpage_t *subpage_init(AddressSpace *as, hwaddr base) 2565db7b5426Sblueswir1 { 2566c227f099SAnthony Liguori subpage_t *mmio; 2567db7b5426Sblueswir1 25682615fabdSVijaya Kumar K mmio = g_malloc0(sizeof(subpage_t) + TARGET_PAGE_SIZE * sizeof(uint16_t)); 2569acc9d80bSJan Kiszka mmio->as = as; 2570db7b5426Sblueswir1 mmio->base = base; 25712c9b15caSPaolo Bonzini memory_region_init_io(&mmio->iomem, NULL, &subpage_ops, mmio, 2572b4fefef9SPeter Crosthwaite NULL, TARGET_PAGE_SIZE); 2573b3b00c78SAvi Kivity mmio->iomem.subpage = true; 2574db7b5426Sblueswir1 #if defined(DEBUG_SUBPAGE) 2575016e9d62SAmos Kong printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__, 2576016e9d62SAmos Kong mmio, base, TARGET_PAGE_SIZE); 2577db7b5426Sblueswir1 #endif 2578b41aac4fSLiu Ping Fan subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, PHYS_SECTION_UNASSIGNED); 2579db7b5426Sblueswir1 2580db7b5426Sblueswir1 return mmio; 2581db7b5426Sblueswir1 } 2582db7b5426Sblueswir1 2583a656e22fSPeter Crosthwaite static uint16_t dummy_section(PhysPageMap *map, AddressSpace *as, 2584a656e22fSPeter Crosthwaite MemoryRegion *mr) 25855312bd8bSAvi Kivity { 2586a656e22fSPeter Crosthwaite assert(as); 25875312bd8bSAvi Kivity MemoryRegionSection section = { 2588a656e22fSPeter Crosthwaite .address_space = as, 25895312bd8bSAvi Kivity .mr = mr, 25905312bd8bSAvi Kivity .offset_within_address_space = 0, 25915312bd8bSAvi Kivity .offset_within_region = 0, 2592052e87b0SPaolo Bonzini .size = int128_2_64(), 25935312bd8bSAvi Kivity }; 25945312bd8bSAvi Kivity 259553cb28cbSMarcel Apfelbaum return phys_section_add(map, §ion); 25965312bd8bSAvi Kivity } 25975312bd8bSAvi Kivity 2598a54c87b6SPeter Maydell MemoryRegion *iotlb_to_region(CPUState *cpu, hwaddr index, MemTxAttrs attrs) 2599aa102231SAvi Kivity { 2600a54c87b6SPeter Maydell int asidx = cpu_asidx_from_attrs(cpu, attrs); 2601a54c87b6SPeter Maydell CPUAddressSpace *cpuas = &cpu->cpu_ases[asidx]; 260232857f4dSPeter Maydell AddressSpaceDispatch *d = atomic_rcu_read(&cpuas->memory_dispatch); 260379e2b9aeSPaolo Bonzini MemoryRegionSection *sections = d->map.sections; 26049d82b5a7SPaolo Bonzini 26059d82b5a7SPaolo Bonzini return sections[index & ~TARGET_PAGE_MASK].mr; 2606aa102231SAvi Kivity } 2607aa102231SAvi Kivity 2608e9179ce1SAvi Kivity static void io_mem_init(void) 2609e9179ce1SAvi Kivity { 26101f6245e5SPaolo Bonzini memory_region_init_io(&io_mem_rom, NULL, &unassigned_mem_ops, NULL, NULL, UINT64_MAX); 26112c9b15caSPaolo Bonzini memory_region_init_io(&io_mem_unassigned, NULL, &unassigned_mem_ops, NULL, 26121f6245e5SPaolo Bonzini NULL, UINT64_MAX); 26138d04fb55SJan Kiszka 26148d04fb55SJan Kiszka /* io_mem_notdirty calls tb_invalidate_phys_page_fast, 26158d04fb55SJan Kiszka * which can be called without the iothread mutex. 26168d04fb55SJan Kiszka */ 26172c9b15caSPaolo Bonzini memory_region_init_io(&io_mem_notdirty, NULL, ¬dirty_mem_ops, NULL, 26181f6245e5SPaolo Bonzini NULL, UINT64_MAX); 26198d04fb55SJan Kiszka memory_region_clear_global_locking(&io_mem_notdirty); 26208d04fb55SJan Kiszka 26212c9b15caSPaolo Bonzini memory_region_init_io(&io_mem_watch, NULL, &watch_mem_ops, NULL, 26221f6245e5SPaolo Bonzini NULL, UINT64_MAX); 2623e9179ce1SAvi Kivity } 2624e9179ce1SAvi Kivity 2625ac1970fbSAvi Kivity static void mem_begin(MemoryListener *listener) 2626ac1970fbSAvi Kivity { 262789ae337aSPaolo Bonzini AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener); 262853cb28cbSMarcel Apfelbaum AddressSpaceDispatch *d = g_new0(AddressSpaceDispatch, 1); 262953cb28cbSMarcel Apfelbaum uint16_t n; 263053cb28cbSMarcel Apfelbaum 2631a656e22fSPeter Crosthwaite n = dummy_section(&d->map, as, &io_mem_unassigned); 263253cb28cbSMarcel Apfelbaum assert(n == PHYS_SECTION_UNASSIGNED); 2633a656e22fSPeter Crosthwaite n = dummy_section(&d->map, as, &io_mem_notdirty); 263453cb28cbSMarcel Apfelbaum assert(n == PHYS_SECTION_NOTDIRTY); 2635a656e22fSPeter Crosthwaite n = dummy_section(&d->map, as, &io_mem_rom); 263653cb28cbSMarcel Apfelbaum assert(n == PHYS_SECTION_ROM); 2637a656e22fSPeter Crosthwaite n = dummy_section(&d->map, as, &io_mem_watch); 263853cb28cbSMarcel Apfelbaum assert(n == PHYS_SECTION_WATCH); 263900752703SPaolo Bonzini 26409736e55bSMichael S. Tsirkin d->phys_map = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .skip = 1 }; 264100752703SPaolo Bonzini d->as = as; 264200752703SPaolo Bonzini as->next_dispatch = d; 264300752703SPaolo Bonzini } 264400752703SPaolo Bonzini 264579e2b9aeSPaolo Bonzini static void address_space_dispatch_free(AddressSpaceDispatch *d) 264679e2b9aeSPaolo Bonzini { 264779e2b9aeSPaolo Bonzini phys_sections_free(&d->map); 264879e2b9aeSPaolo Bonzini g_free(d); 264979e2b9aeSPaolo Bonzini } 265079e2b9aeSPaolo Bonzini 265100752703SPaolo Bonzini static void mem_commit(MemoryListener *listener) 265200752703SPaolo Bonzini { 265300752703SPaolo Bonzini AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener); 26540475d94fSPaolo Bonzini AddressSpaceDispatch *cur = as->dispatch; 26550475d94fSPaolo Bonzini AddressSpaceDispatch *next = as->next_dispatch; 2656ac1970fbSAvi Kivity 265753cb28cbSMarcel Apfelbaum phys_page_compact_all(next, next->map.nodes_nb); 2658b35ba30fSMichael S. Tsirkin 265979e2b9aeSPaolo Bonzini atomic_rcu_set(&as->dispatch, next); 266053cb28cbSMarcel Apfelbaum if (cur) { 266179e2b9aeSPaolo Bonzini call_rcu(cur, address_space_dispatch_free, rcu); 2662ac1970fbSAvi Kivity } 26639affd6fcSPaolo Bonzini } 26649affd6fcSPaolo Bonzini 26651d71148eSAvi Kivity static void tcg_commit(MemoryListener *listener) 266650c1e149SAvi Kivity { 266732857f4dSPeter Maydell CPUAddressSpace *cpuas; 266832857f4dSPeter Maydell AddressSpaceDispatch *d; 2669117712c3SAvi Kivity 2670117712c3SAvi Kivity /* since each CPU stores ram addresses in its TLB cache, we must 2671117712c3SAvi Kivity reset the modified entries */ 267232857f4dSPeter Maydell cpuas = container_of(listener, CPUAddressSpace, tcg_as_listener); 267332857f4dSPeter Maydell cpu_reloading_memory_map(); 267432857f4dSPeter Maydell /* The CPU and TLB are protected by the iothread lock. 267532857f4dSPeter Maydell * We reload the dispatch pointer now because cpu_reloading_memory_map() 267632857f4dSPeter Maydell * may have split the RCU critical section. 267732857f4dSPeter Maydell */ 267832857f4dSPeter Maydell d = atomic_rcu_read(&cpuas->as->dispatch); 2679f35e44e7SAlex Bennée atomic_rcu_set(&cpuas->memory_dispatch, d); 2680d10eb08fSAlex Bennée tlb_flush(cpuas->cpu); 268150c1e149SAvi Kivity } 268250c1e149SAvi Kivity 2683ac1970fbSAvi Kivity void address_space_init_dispatch(AddressSpace *as) 2684ac1970fbSAvi Kivity { 268500752703SPaolo Bonzini as->dispatch = NULL; 268689ae337aSPaolo Bonzini as->dispatch_listener = (MemoryListener) { 2687ac1970fbSAvi Kivity .begin = mem_begin, 268800752703SPaolo Bonzini .commit = mem_commit, 2689ac1970fbSAvi Kivity .region_add = mem_add, 2690ac1970fbSAvi Kivity .region_nop = mem_add, 2691ac1970fbSAvi Kivity .priority = 0, 2692ac1970fbSAvi Kivity }; 269389ae337aSPaolo Bonzini memory_listener_register(&as->dispatch_listener, as); 2694ac1970fbSAvi Kivity } 2695ac1970fbSAvi Kivity 26966e48e8f9SPaolo Bonzini void address_space_unregister(AddressSpace *as) 26976e48e8f9SPaolo Bonzini { 26986e48e8f9SPaolo Bonzini memory_listener_unregister(&as->dispatch_listener); 26996e48e8f9SPaolo Bonzini } 27006e48e8f9SPaolo Bonzini 270183f3c251SAvi Kivity void address_space_destroy_dispatch(AddressSpace *as) 270283f3c251SAvi Kivity { 270383f3c251SAvi Kivity AddressSpaceDispatch *d = as->dispatch; 270483f3c251SAvi Kivity 270579e2b9aeSPaolo Bonzini atomic_rcu_set(&as->dispatch, NULL); 270679e2b9aeSPaolo Bonzini if (d) { 270779e2b9aeSPaolo Bonzini call_rcu(d, address_space_dispatch_free, rcu); 270879e2b9aeSPaolo Bonzini } 270983f3c251SAvi Kivity } 271083f3c251SAvi Kivity 271162152b8aSAvi Kivity static void memory_map_init(void) 271262152b8aSAvi Kivity { 27137267c094SAnthony Liguori system_memory = g_malloc(sizeof(*system_memory)); 271403f49957SPaolo Bonzini 271557271d63SPaolo Bonzini memory_region_init(system_memory, NULL, "system", UINT64_MAX); 27167dca8043SAlexey Kardashevskiy address_space_init(&address_space_memory, system_memory, "memory"); 2717309cb471SAvi Kivity 27187267c094SAnthony Liguori system_io = g_malloc(sizeof(*system_io)); 27193bb28b72SJan Kiszka memory_region_init_io(system_io, NULL, &unassigned_io_ops, NULL, "io", 27203bb28b72SJan Kiszka 65536); 27217dca8043SAlexey Kardashevskiy address_space_init(&address_space_io, system_io, "I/O"); 27222641689aSliguang } 272362152b8aSAvi Kivity 272462152b8aSAvi Kivity MemoryRegion *get_system_memory(void) 272562152b8aSAvi Kivity { 272662152b8aSAvi Kivity return system_memory; 272762152b8aSAvi Kivity } 272862152b8aSAvi Kivity 2729309cb471SAvi Kivity MemoryRegion *get_system_io(void) 2730309cb471SAvi Kivity { 2731309cb471SAvi Kivity return system_io; 2732309cb471SAvi Kivity } 2733309cb471SAvi Kivity 2734e2eef170Spbrook #endif /* !defined(CONFIG_USER_ONLY) */ 2735e2eef170Spbrook 273613eb76e0Sbellard /* physical memory access (slow version, mainly for debug) */ 273713eb76e0Sbellard #if defined(CONFIG_USER_ONLY) 2738f17ec444SAndreas Färber int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, 2739a68fe89cSPaul Brook uint8_t *buf, int len, int is_write) 274013eb76e0Sbellard { 274113eb76e0Sbellard int l, flags; 274213eb76e0Sbellard target_ulong page; 274353a5960aSpbrook void * p; 274413eb76e0Sbellard 274513eb76e0Sbellard while (len > 0) { 274613eb76e0Sbellard page = addr & TARGET_PAGE_MASK; 274713eb76e0Sbellard l = (page + TARGET_PAGE_SIZE) - addr; 274813eb76e0Sbellard if (l > len) 274913eb76e0Sbellard l = len; 275013eb76e0Sbellard flags = page_get_flags(page); 275113eb76e0Sbellard if (!(flags & PAGE_VALID)) 2752a68fe89cSPaul Brook return -1; 275313eb76e0Sbellard if (is_write) { 275413eb76e0Sbellard if (!(flags & PAGE_WRITE)) 2755a68fe89cSPaul Brook return -1; 2756579a97f7Sbellard /* XXX: this code should not depend on lock_user */ 275772fb7daaSaurel32 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0))) 2758a68fe89cSPaul Brook return -1; 275972fb7daaSaurel32 memcpy(p, buf, l); 276072fb7daaSaurel32 unlock_user(p, addr, l); 276113eb76e0Sbellard } else { 276213eb76e0Sbellard if (!(flags & PAGE_READ)) 2763a68fe89cSPaul Brook return -1; 2764579a97f7Sbellard /* XXX: this code should not depend on lock_user */ 276572fb7daaSaurel32 if (!(p = lock_user(VERIFY_READ, addr, l, 1))) 2766a68fe89cSPaul Brook return -1; 276772fb7daaSaurel32 memcpy(buf, p, l); 27685b257578Saurel32 unlock_user(p, addr, 0); 276913eb76e0Sbellard } 277013eb76e0Sbellard len -= l; 277113eb76e0Sbellard buf += l; 277213eb76e0Sbellard addr += l; 277313eb76e0Sbellard } 2774a68fe89cSPaul Brook return 0; 277513eb76e0Sbellard } 27768df1cd07Sbellard 277713eb76e0Sbellard #else 277851d7a9ebSAnthony PERARD 2779845b6214SPaolo Bonzini static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr, 2780a8170e5eSAvi Kivity hwaddr length) 278151d7a9ebSAnthony PERARD { 2782845b6214SPaolo Bonzini uint8_t dirty_log_mask = memory_region_get_dirty_log_mask(mr); 27830878d0e1SPaolo Bonzini addr += memory_region_get_ram_addr(mr); 27840878d0e1SPaolo Bonzini 2785e87f7778SPaolo Bonzini /* No early return if dirty_log_mask is or becomes 0, because 2786e87f7778SPaolo Bonzini * cpu_physical_memory_set_dirty_range will still call 2787e87f7778SPaolo Bonzini * xen_modified_memory. 2788e87f7778SPaolo Bonzini */ 2789e87f7778SPaolo Bonzini if (dirty_log_mask) { 2790e87f7778SPaolo Bonzini dirty_log_mask = 2791e87f7778SPaolo Bonzini cpu_physical_memory_range_includes_clean(addr, length, dirty_log_mask); 2792e87f7778SPaolo Bonzini } 2793845b6214SPaolo Bonzini if (dirty_log_mask & (1 << DIRTY_MEMORY_CODE)) { 2794ba051fb5SAlex Bennée tb_lock(); 279535865339SPaolo Bonzini tb_invalidate_phys_range(addr, addr + length); 2796ba051fb5SAlex Bennée tb_unlock(); 2797845b6214SPaolo Bonzini dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE); 2798845b6214SPaolo Bonzini } 279958d2707eSPaolo Bonzini cpu_physical_memory_set_dirty_range(addr, length, dirty_log_mask); 280049dfcec4SPaolo Bonzini } 280151d7a9ebSAnthony PERARD 280223326164SRichard Henderson static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) 280382f2563fSPaolo Bonzini { 2804e1622f4bSPaolo Bonzini unsigned access_size_max = mr->ops->valid.max_access_size; 280523326164SRichard Henderson 280623326164SRichard Henderson /* Regions are assumed to support 1-4 byte accesses unless 280723326164SRichard Henderson otherwise specified. */ 280823326164SRichard Henderson if (access_size_max == 0) { 280923326164SRichard Henderson access_size_max = 4; 281082f2563fSPaolo Bonzini } 281123326164SRichard Henderson 281223326164SRichard Henderson /* Bound the maximum access by the alignment of the address. */ 281323326164SRichard Henderson if (!mr->ops->impl.unaligned) { 281423326164SRichard Henderson unsigned align_size_max = addr & -addr; 281523326164SRichard Henderson if (align_size_max != 0 && align_size_max < access_size_max) { 281623326164SRichard Henderson access_size_max = align_size_max; 281723326164SRichard Henderson } 281823326164SRichard Henderson } 281923326164SRichard Henderson 282023326164SRichard Henderson /* Don't attempt accesses larger than the maximum. */ 282123326164SRichard Henderson if (l > access_size_max) { 282223326164SRichard Henderson l = access_size_max; 282323326164SRichard Henderson } 28246554f5c0SPeter Maydell l = pow2floor(l); 282523326164SRichard Henderson 282623326164SRichard Henderson return l; 282782f2563fSPaolo Bonzini } 282882f2563fSPaolo Bonzini 28294840f10eSJan Kiszka static bool prepare_mmio_access(MemoryRegion *mr) 2830125b3806SPaolo Bonzini { 28314840f10eSJan Kiszka bool unlocked = !qemu_mutex_iothread_locked(); 28324840f10eSJan Kiszka bool release_lock = false; 28334840f10eSJan Kiszka 28344840f10eSJan Kiszka if (unlocked && mr->global_locking) { 28354840f10eSJan Kiszka qemu_mutex_lock_iothread(); 28364840f10eSJan Kiszka unlocked = false; 28374840f10eSJan Kiszka release_lock = true; 2838125b3806SPaolo Bonzini } 28394840f10eSJan Kiszka if (mr->flush_coalesced_mmio) { 28404840f10eSJan Kiszka if (unlocked) { 28414840f10eSJan Kiszka qemu_mutex_lock_iothread(); 28424840f10eSJan Kiszka } 28434840f10eSJan Kiszka qemu_flush_coalesced_mmio_buffer(); 28444840f10eSJan Kiszka if (unlocked) { 28454840f10eSJan Kiszka qemu_mutex_unlock_iothread(); 28464840f10eSJan Kiszka } 28474840f10eSJan Kiszka } 28484840f10eSJan Kiszka 28494840f10eSJan Kiszka return release_lock; 2850125b3806SPaolo Bonzini } 2851125b3806SPaolo Bonzini 2852a203ac70SPaolo Bonzini /* Called within RCU critical section. */ 2853a203ac70SPaolo Bonzini static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr, 2854a203ac70SPaolo Bonzini MemTxAttrs attrs, 2855a203ac70SPaolo Bonzini const uint8_t *buf, 2856a203ac70SPaolo Bonzini int len, hwaddr addr1, 2857a203ac70SPaolo Bonzini hwaddr l, MemoryRegion *mr) 285813eb76e0Sbellard { 285913eb76e0Sbellard uint8_t *ptr; 2860791af8c8SPaolo Bonzini uint64_t val; 28613b643495SPeter Maydell MemTxResult result = MEMTX_OK; 28624840f10eSJan Kiszka bool release_lock = false; 286313eb76e0Sbellard 2864a203ac70SPaolo Bonzini for (;;) { 2865eb7eeb88SPaolo Bonzini if (!memory_access_is_direct(mr, true)) { 28664840f10eSJan Kiszka release_lock |= prepare_mmio_access(mr); 28675c8a00ceSPaolo Bonzini l = memory_access_size(mr, l, addr1); 28684917cf44SAndreas Färber /* XXX: could force current_cpu to NULL to avoid 28696a00d601Sbellard potential bugs */ 287023326164SRichard Henderson switch (l) { 287123326164SRichard Henderson case 8: 287223326164SRichard Henderson /* 64 bit write access */ 287323326164SRichard Henderson val = ldq_p(buf); 28743b643495SPeter Maydell result |= memory_region_dispatch_write(mr, addr1, val, 8, 28753b643495SPeter Maydell attrs); 287623326164SRichard Henderson break; 287723326164SRichard Henderson case 4: 28781c213d19Sbellard /* 32 bit write access */ 28796da67de6SLadi Prosek val = (uint32_t)ldl_p(buf); 28803b643495SPeter Maydell result |= memory_region_dispatch_write(mr, addr1, val, 4, 28813b643495SPeter Maydell attrs); 288223326164SRichard Henderson break; 288323326164SRichard Henderson case 2: 28841c213d19Sbellard /* 16 bit write access */ 2885c27004ecSbellard val = lduw_p(buf); 28863b643495SPeter Maydell result |= memory_region_dispatch_write(mr, addr1, val, 2, 28873b643495SPeter Maydell attrs); 288823326164SRichard Henderson break; 288923326164SRichard Henderson case 1: 28901c213d19Sbellard /* 8 bit write access */ 2891c27004ecSbellard val = ldub_p(buf); 28923b643495SPeter Maydell result |= memory_region_dispatch_write(mr, addr1, val, 1, 28933b643495SPeter Maydell attrs); 289423326164SRichard Henderson break; 289523326164SRichard Henderson default: 289623326164SRichard Henderson abort(); 289713eb76e0Sbellard } 28982bbfa05dSPaolo Bonzini } else { 289913eb76e0Sbellard /* RAM case */ 29000878d0e1SPaolo Bonzini ptr = qemu_map_ram_ptr(mr->ram_block, addr1); 290113eb76e0Sbellard memcpy(ptr, buf, l); 2902845b6214SPaolo Bonzini invalidate_and_set_dirty(mr, addr1, l); 29033a7d929eSbellard } 2904eb7eeb88SPaolo Bonzini 2905eb7eeb88SPaolo Bonzini if (release_lock) { 2906eb7eeb88SPaolo Bonzini qemu_mutex_unlock_iothread(); 2907eb7eeb88SPaolo Bonzini release_lock = false; 2908eb7eeb88SPaolo Bonzini } 2909eb7eeb88SPaolo Bonzini 2910eb7eeb88SPaolo Bonzini len -= l; 2911eb7eeb88SPaolo Bonzini buf += l; 2912eb7eeb88SPaolo Bonzini addr += l; 2913a203ac70SPaolo Bonzini 2914a203ac70SPaolo Bonzini if (!len) { 2915a203ac70SPaolo Bonzini break; 2916eb7eeb88SPaolo Bonzini } 2917a203ac70SPaolo Bonzini 2918a203ac70SPaolo Bonzini l = len; 2919a203ac70SPaolo Bonzini mr = address_space_translate(as, addr, &addr1, &l, true); 2920a203ac70SPaolo Bonzini } 2921eb7eeb88SPaolo Bonzini 2922eb7eeb88SPaolo Bonzini return result; 2923eb7eeb88SPaolo Bonzini } 2924eb7eeb88SPaolo Bonzini 2925a203ac70SPaolo Bonzini MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, 2926a203ac70SPaolo Bonzini const uint8_t *buf, int len) 2927eb7eeb88SPaolo Bonzini { 2928eb7eeb88SPaolo Bonzini hwaddr l; 2929eb7eeb88SPaolo Bonzini hwaddr addr1; 2930eb7eeb88SPaolo Bonzini MemoryRegion *mr; 2931eb7eeb88SPaolo Bonzini MemTxResult result = MEMTX_OK; 2932a203ac70SPaolo Bonzini 2933a203ac70SPaolo Bonzini if (len > 0) { 2934a203ac70SPaolo Bonzini rcu_read_lock(); 2935a203ac70SPaolo Bonzini l = len; 2936a203ac70SPaolo Bonzini mr = address_space_translate(as, addr, &addr1, &l, true); 2937a203ac70SPaolo Bonzini result = address_space_write_continue(as, addr, attrs, buf, len, 2938a203ac70SPaolo Bonzini addr1, l, mr); 2939a203ac70SPaolo Bonzini rcu_read_unlock(); 2940a203ac70SPaolo Bonzini } 2941a203ac70SPaolo Bonzini 2942a203ac70SPaolo Bonzini return result; 2943a203ac70SPaolo Bonzini } 2944a203ac70SPaolo Bonzini 2945a203ac70SPaolo Bonzini /* Called within RCU critical section. */ 2946a203ac70SPaolo Bonzini MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr, 2947a203ac70SPaolo Bonzini MemTxAttrs attrs, uint8_t *buf, 2948a203ac70SPaolo Bonzini int len, hwaddr addr1, hwaddr l, 2949a203ac70SPaolo Bonzini MemoryRegion *mr) 2950a203ac70SPaolo Bonzini { 2951a203ac70SPaolo Bonzini uint8_t *ptr; 2952a203ac70SPaolo Bonzini uint64_t val; 2953a203ac70SPaolo Bonzini MemTxResult result = MEMTX_OK; 2954eb7eeb88SPaolo Bonzini bool release_lock = false; 2955eb7eeb88SPaolo Bonzini 2956a203ac70SPaolo Bonzini for (;;) { 2957eb7eeb88SPaolo Bonzini if (!memory_access_is_direct(mr, false)) { 295813eb76e0Sbellard /* I/O case */ 29594840f10eSJan Kiszka release_lock |= prepare_mmio_access(mr); 29605c8a00ceSPaolo Bonzini l = memory_access_size(mr, l, addr1); 296123326164SRichard Henderson switch (l) { 296223326164SRichard Henderson case 8: 296323326164SRichard Henderson /* 64 bit read access */ 29643b643495SPeter Maydell result |= memory_region_dispatch_read(mr, addr1, &val, 8, 29653b643495SPeter Maydell attrs); 296623326164SRichard Henderson stq_p(buf, val); 296723326164SRichard Henderson break; 296823326164SRichard Henderson case 4: 296913eb76e0Sbellard /* 32 bit read access */ 29703b643495SPeter Maydell result |= memory_region_dispatch_read(mr, addr1, &val, 4, 29713b643495SPeter Maydell attrs); 2972c27004ecSbellard stl_p(buf, val); 297323326164SRichard Henderson break; 297423326164SRichard Henderson case 2: 297513eb76e0Sbellard /* 16 bit read access */ 29763b643495SPeter Maydell result |= memory_region_dispatch_read(mr, addr1, &val, 2, 29773b643495SPeter Maydell attrs); 2978c27004ecSbellard stw_p(buf, val); 297923326164SRichard Henderson break; 298023326164SRichard Henderson case 1: 29811c213d19Sbellard /* 8 bit read access */ 29823b643495SPeter Maydell result |= memory_region_dispatch_read(mr, addr1, &val, 1, 29833b643495SPeter Maydell attrs); 2984c27004ecSbellard stb_p(buf, val); 298523326164SRichard Henderson break; 298623326164SRichard Henderson default: 298723326164SRichard Henderson abort(); 298813eb76e0Sbellard } 298913eb76e0Sbellard } else { 299013eb76e0Sbellard /* RAM case */ 29910878d0e1SPaolo Bonzini ptr = qemu_map_ram_ptr(mr->ram_block, addr1); 2992f3705d53SAvi Kivity memcpy(buf, ptr, l); 299313eb76e0Sbellard } 29944840f10eSJan Kiszka 29954840f10eSJan Kiszka if (release_lock) { 29964840f10eSJan Kiszka qemu_mutex_unlock_iothread(); 29974840f10eSJan Kiszka release_lock = false; 29984840f10eSJan Kiszka } 29994840f10eSJan Kiszka 300013eb76e0Sbellard len -= l; 300113eb76e0Sbellard buf += l; 300213eb76e0Sbellard addr += l; 3003a203ac70SPaolo Bonzini 3004a203ac70SPaolo Bonzini if (!len) { 3005a203ac70SPaolo Bonzini break; 300613eb76e0Sbellard } 3007a203ac70SPaolo Bonzini 3008a203ac70SPaolo Bonzini l = len; 3009a203ac70SPaolo Bonzini mr = address_space_translate(as, addr, &addr1, &l, false); 3010a203ac70SPaolo Bonzini } 3011a203ac70SPaolo Bonzini 3012a203ac70SPaolo Bonzini return result; 3013a203ac70SPaolo Bonzini } 3014a203ac70SPaolo Bonzini 30153cc8f884SPaolo Bonzini MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr, 30163cc8f884SPaolo Bonzini MemTxAttrs attrs, uint8_t *buf, int len) 3017a203ac70SPaolo Bonzini { 3018a203ac70SPaolo Bonzini hwaddr l; 3019a203ac70SPaolo Bonzini hwaddr addr1; 3020a203ac70SPaolo Bonzini MemoryRegion *mr; 3021a203ac70SPaolo Bonzini MemTxResult result = MEMTX_OK; 3022a203ac70SPaolo Bonzini 3023a203ac70SPaolo Bonzini if (len > 0) { 3024a203ac70SPaolo Bonzini rcu_read_lock(); 3025a203ac70SPaolo Bonzini l = len; 3026a203ac70SPaolo Bonzini mr = address_space_translate(as, addr, &addr1, &l, false); 3027a203ac70SPaolo Bonzini result = address_space_read_continue(as, addr, attrs, buf, len, 3028a203ac70SPaolo Bonzini addr1, l, mr); 302941063e1eSPaolo Bonzini rcu_read_unlock(); 3030a203ac70SPaolo Bonzini } 3031fd8aaa76SPaolo Bonzini 30323b643495SPeter Maydell return result; 303313eb76e0Sbellard } 30348df1cd07Sbellard 3035eb7eeb88SPaolo Bonzini MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, 3036eb7eeb88SPaolo Bonzini uint8_t *buf, int len, bool is_write) 3037ac1970fbSAvi Kivity { 3038eb7eeb88SPaolo Bonzini if (is_write) { 3039eb7eeb88SPaolo Bonzini return address_space_write(as, addr, attrs, (uint8_t *)buf, len); 3040eb7eeb88SPaolo Bonzini } else { 3041eb7eeb88SPaolo Bonzini return address_space_read(as, addr, attrs, (uint8_t *)buf, len); 3042ac1970fbSAvi Kivity } 3043ac1970fbSAvi Kivity } 3044ac1970fbSAvi Kivity 3045a8170e5eSAvi Kivity void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf, 3046ac1970fbSAvi Kivity int len, int is_write) 3047ac1970fbSAvi Kivity { 30485c9eb028SPeter Maydell address_space_rw(&address_space_memory, addr, MEMTXATTRS_UNSPECIFIED, 30495c9eb028SPeter Maydell buf, len, is_write); 3050ac1970fbSAvi Kivity } 3051ac1970fbSAvi Kivity 3052582b55a9SAlexander Graf enum write_rom_type { 3053582b55a9SAlexander Graf WRITE_DATA, 3054582b55a9SAlexander Graf FLUSH_CACHE, 3055582b55a9SAlexander Graf }; 3056582b55a9SAlexander Graf 30572a221651SEdgar E. Iglesias static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as, 3058582b55a9SAlexander Graf hwaddr addr, const uint8_t *buf, int len, enum write_rom_type type) 3059d0ecd2aaSbellard { 3060149f54b5SPaolo Bonzini hwaddr l; 3061d0ecd2aaSbellard uint8_t *ptr; 3062149f54b5SPaolo Bonzini hwaddr addr1; 30635c8a00ceSPaolo Bonzini MemoryRegion *mr; 3064d0ecd2aaSbellard 306541063e1eSPaolo Bonzini rcu_read_lock(); 3066d0ecd2aaSbellard while (len > 0) { 3067d0ecd2aaSbellard l = len; 30682a221651SEdgar E. Iglesias mr = address_space_translate(as, addr, &addr1, &l, true); 3069d0ecd2aaSbellard 30705c8a00ceSPaolo Bonzini if (!(memory_region_is_ram(mr) || 30715c8a00ceSPaolo Bonzini memory_region_is_romd(mr))) { 3072b242e0e0SPaolo Bonzini l = memory_access_size(mr, l, addr1); 3073d0ecd2aaSbellard } else { 3074d0ecd2aaSbellard /* ROM/RAM case */ 30750878d0e1SPaolo Bonzini ptr = qemu_map_ram_ptr(mr->ram_block, addr1); 3076582b55a9SAlexander Graf switch (type) { 3077582b55a9SAlexander Graf case WRITE_DATA: 3078d0ecd2aaSbellard memcpy(ptr, buf, l); 3079845b6214SPaolo Bonzini invalidate_and_set_dirty(mr, addr1, l); 3080582b55a9SAlexander Graf break; 3081582b55a9SAlexander Graf case FLUSH_CACHE: 3082582b55a9SAlexander Graf flush_icache_range((uintptr_t)ptr, (uintptr_t)ptr + l); 3083582b55a9SAlexander Graf break; 3084582b55a9SAlexander Graf } 3085d0ecd2aaSbellard } 3086d0ecd2aaSbellard len -= l; 3087d0ecd2aaSbellard buf += l; 3088d0ecd2aaSbellard addr += l; 3089d0ecd2aaSbellard } 309041063e1eSPaolo Bonzini rcu_read_unlock(); 3091d0ecd2aaSbellard } 3092d0ecd2aaSbellard 3093582b55a9SAlexander Graf /* used for ROM loading : can write in RAM and ROM */ 30942a221651SEdgar E. Iglesias void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr, 3095582b55a9SAlexander Graf const uint8_t *buf, int len) 3096582b55a9SAlexander Graf { 30972a221651SEdgar E. Iglesias cpu_physical_memory_write_rom_internal(as, addr, buf, len, WRITE_DATA); 3098582b55a9SAlexander Graf } 3099582b55a9SAlexander Graf 3100582b55a9SAlexander Graf void cpu_flush_icache_range(hwaddr start, int len) 3101582b55a9SAlexander Graf { 3102582b55a9SAlexander Graf /* 3103582b55a9SAlexander Graf * This function should do the same thing as an icache flush that was 3104582b55a9SAlexander Graf * triggered from within the guest. For TCG we are always cache coherent, 3105582b55a9SAlexander Graf * so there is no need to flush anything. For KVM / Xen we need to flush 3106582b55a9SAlexander Graf * the host's instruction cache at least. 3107582b55a9SAlexander Graf */ 3108582b55a9SAlexander Graf if (tcg_enabled()) { 3109582b55a9SAlexander Graf return; 3110582b55a9SAlexander Graf } 3111582b55a9SAlexander Graf 31122a221651SEdgar E. Iglesias cpu_physical_memory_write_rom_internal(&address_space_memory, 31132a221651SEdgar E. Iglesias start, NULL, len, FLUSH_CACHE); 3114582b55a9SAlexander Graf } 3115582b55a9SAlexander Graf 31166d16c2f8Saliguori typedef struct { 3117d3e71559SPaolo Bonzini MemoryRegion *mr; 31186d16c2f8Saliguori void *buffer; 3119a8170e5eSAvi Kivity hwaddr addr; 3120a8170e5eSAvi Kivity hwaddr len; 3121c2cba0ffSFam Zheng bool in_use; 31226d16c2f8Saliguori } BounceBuffer; 31236d16c2f8Saliguori 31246d16c2f8Saliguori static BounceBuffer bounce; 31256d16c2f8Saliguori 3126ba223c29Saliguori typedef struct MapClient { 3127e95205e1SFam Zheng QEMUBH *bh; 312872cf2d4fSBlue Swirl QLIST_ENTRY(MapClient) link; 3129ba223c29Saliguori } MapClient; 3130ba223c29Saliguori 313138e047b5SFam Zheng QemuMutex map_client_list_lock; 313272cf2d4fSBlue Swirl static QLIST_HEAD(map_client_list, MapClient) map_client_list 313372cf2d4fSBlue Swirl = QLIST_HEAD_INITIALIZER(map_client_list); 3134ba223c29Saliguori 3135e95205e1SFam Zheng static void cpu_unregister_map_client_do(MapClient *client) 3136ba223c29Saliguori { 313772cf2d4fSBlue Swirl QLIST_REMOVE(client, link); 31387267c094SAnthony Liguori g_free(client); 3139ba223c29Saliguori } 3140ba223c29Saliguori 314133b6c2edSFam Zheng static void cpu_notify_map_clients_locked(void) 3142ba223c29Saliguori { 3143ba223c29Saliguori MapClient *client; 3144ba223c29Saliguori 314572cf2d4fSBlue Swirl while (!QLIST_EMPTY(&map_client_list)) { 314672cf2d4fSBlue Swirl client = QLIST_FIRST(&map_client_list); 3147e95205e1SFam Zheng qemu_bh_schedule(client->bh); 3148e95205e1SFam Zheng cpu_unregister_map_client_do(client); 3149ba223c29Saliguori } 3150ba223c29Saliguori } 3151ba223c29Saliguori 3152e95205e1SFam Zheng void cpu_register_map_client(QEMUBH *bh) 3153d0ecd2aaSbellard { 3154d0ecd2aaSbellard MapClient *client = g_malloc(sizeof(*client)); 3155d0ecd2aaSbellard 315638e047b5SFam Zheng qemu_mutex_lock(&map_client_list_lock); 3157e95205e1SFam Zheng client->bh = bh; 3158d0ecd2aaSbellard QLIST_INSERT_HEAD(&map_client_list, client, link); 315933b6c2edSFam Zheng if (!atomic_read(&bounce.in_use)) { 316033b6c2edSFam Zheng cpu_notify_map_clients_locked(); 316133b6c2edSFam Zheng } 316238e047b5SFam Zheng qemu_mutex_unlock(&map_client_list_lock); 3163d0ecd2aaSbellard } 3164d0ecd2aaSbellard 316538e047b5SFam Zheng void cpu_exec_init_all(void) 316638e047b5SFam Zheng { 316738e047b5SFam Zheng qemu_mutex_init(&ram_list.mutex); 316820bccb82SPeter Maydell /* The data structures we set up here depend on knowing the page size, 316920bccb82SPeter Maydell * so no more changes can be made after this point. 317020bccb82SPeter Maydell * In an ideal world, nothing we did before we had finished the 317120bccb82SPeter Maydell * machine setup would care about the target page size, and we could 317220bccb82SPeter Maydell * do this much later, rather than requiring board models to state 317320bccb82SPeter Maydell * up front what their requirements are. 317420bccb82SPeter Maydell */ 317520bccb82SPeter Maydell finalize_target_page_bits(); 317638e047b5SFam Zheng io_mem_init(); 3177680a4783SPaolo Bonzini memory_map_init(); 317838e047b5SFam Zheng qemu_mutex_init(&map_client_list_lock); 317938e047b5SFam Zheng } 318038e047b5SFam Zheng 3181e95205e1SFam Zheng void cpu_unregister_map_client(QEMUBH *bh) 3182d0ecd2aaSbellard { 3183e95205e1SFam Zheng MapClient *client; 3184d0ecd2aaSbellard 3185e95205e1SFam Zheng qemu_mutex_lock(&map_client_list_lock); 3186e95205e1SFam Zheng QLIST_FOREACH(client, &map_client_list, link) { 3187e95205e1SFam Zheng if (client->bh == bh) { 3188e95205e1SFam Zheng cpu_unregister_map_client_do(client); 3189e95205e1SFam Zheng break; 3190e95205e1SFam Zheng } 3191e95205e1SFam Zheng } 3192e95205e1SFam Zheng qemu_mutex_unlock(&map_client_list_lock); 3193d0ecd2aaSbellard } 3194d0ecd2aaSbellard 3195d0ecd2aaSbellard static void cpu_notify_map_clients(void) 3196d0ecd2aaSbellard { 319738e047b5SFam Zheng qemu_mutex_lock(&map_client_list_lock); 319833b6c2edSFam Zheng cpu_notify_map_clients_locked(); 319938e047b5SFam Zheng qemu_mutex_unlock(&map_client_list_lock); 32006d16c2f8Saliguori } 32016d16c2f8Saliguori 320251644ab7SPaolo Bonzini bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_write) 320351644ab7SPaolo Bonzini { 32045c8a00ceSPaolo Bonzini MemoryRegion *mr; 320551644ab7SPaolo Bonzini hwaddr l, xlat; 320651644ab7SPaolo Bonzini 320741063e1eSPaolo Bonzini rcu_read_lock(); 320851644ab7SPaolo Bonzini while (len > 0) { 320951644ab7SPaolo Bonzini l = len; 32105c8a00ceSPaolo Bonzini mr = address_space_translate(as, addr, &xlat, &l, is_write); 32115c8a00ceSPaolo Bonzini if (!memory_access_is_direct(mr, is_write)) { 32125c8a00ceSPaolo Bonzini l = memory_access_size(mr, l, addr); 32135c8a00ceSPaolo Bonzini if (!memory_region_access_valid(mr, xlat, l, is_write)) { 32145ad4a2b7SRoman Kapl rcu_read_unlock(); 321551644ab7SPaolo Bonzini return false; 321651644ab7SPaolo Bonzini } 321751644ab7SPaolo Bonzini } 321851644ab7SPaolo Bonzini 321951644ab7SPaolo Bonzini len -= l; 322051644ab7SPaolo Bonzini addr += l; 322151644ab7SPaolo Bonzini } 322241063e1eSPaolo Bonzini rcu_read_unlock(); 322351644ab7SPaolo Bonzini return true; 322451644ab7SPaolo Bonzini } 322551644ab7SPaolo Bonzini 3226715c31ecSPaolo Bonzini static hwaddr 3227715c31ecSPaolo Bonzini address_space_extend_translation(AddressSpace *as, hwaddr addr, hwaddr target_len, 3228715c31ecSPaolo Bonzini MemoryRegion *mr, hwaddr base, hwaddr len, 3229715c31ecSPaolo Bonzini bool is_write) 3230715c31ecSPaolo Bonzini { 3231715c31ecSPaolo Bonzini hwaddr done = 0; 3232715c31ecSPaolo Bonzini hwaddr xlat; 3233715c31ecSPaolo Bonzini MemoryRegion *this_mr; 3234715c31ecSPaolo Bonzini 3235715c31ecSPaolo Bonzini for (;;) { 3236715c31ecSPaolo Bonzini target_len -= len; 3237715c31ecSPaolo Bonzini addr += len; 3238715c31ecSPaolo Bonzini done += len; 3239715c31ecSPaolo Bonzini if (target_len == 0) { 3240715c31ecSPaolo Bonzini return done; 3241715c31ecSPaolo Bonzini } 3242715c31ecSPaolo Bonzini 3243715c31ecSPaolo Bonzini len = target_len; 3244715c31ecSPaolo Bonzini this_mr = address_space_translate(as, addr, &xlat, &len, is_write); 3245715c31ecSPaolo Bonzini if (this_mr != mr || xlat != base + done) { 3246715c31ecSPaolo Bonzini return done; 3247715c31ecSPaolo Bonzini } 3248715c31ecSPaolo Bonzini } 3249715c31ecSPaolo Bonzini } 3250715c31ecSPaolo Bonzini 32516d16c2f8Saliguori /* Map a physical memory region into a host virtual address. 32526d16c2f8Saliguori * May map a subset of the requested range, given by and returned in *plen. 32536d16c2f8Saliguori * May return NULL if resources needed to perform the mapping are exhausted. 32546d16c2f8Saliguori * Use only for reads OR writes - not for read-modify-write operations. 3255ba223c29Saliguori * Use cpu_register_map_client() to know when retrying the map operation is 3256ba223c29Saliguori * likely to succeed. 32576d16c2f8Saliguori */ 3258ac1970fbSAvi Kivity void *address_space_map(AddressSpace *as, 3259a8170e5eSAvi Kivity hwaddr addr, 3260a8170e5eSAvi Kivity hwaddr *plen, 3261ac1970fbSAvi Kivity bool is_write) 32626d16c2f8Saliguori { 3263a8170e5eSAvi Kivity hwaddr len = *plen; 3264715c31ecSPaolo Bonzini hwaddr l, xlat; 3265715c31ecSPaolo Bonzini MemoryRegion *mr; 3266e81bcda5SPaolo Bonzini void *ptr; 32676d16c2f8Saliguori 3268e3127ae0SPaolo Bonzini if (len == 0) { 3269e3127ae0SPaolo Bonzini return NULL; 3270e3127ae0SPaolo Bonzini } 3271e3127ae0SPaolo Bonzini 32726d16c2f8Saliguori l = len; 327341063e1eSPaolo Bonzini rcu_read_lock(); 32745c8a00ceSPaolo Bonzini mr = address_space_translate(as, addr, &xlat, &l, is_write); 327541063e1eSPaolo Bonzini 32765c8a00ceSPaolo Bonzini if (!memory_access_is_direct(mr, is_write)) { 3277c2cba0ffSFam Zheng if (atomic_xchg(&bounce.in_use, true)) { 327841063e1eSPaolo Bonzini rcu_read_unlock(); 3279e3127ae0SPaolo Bonzini return NULL; 32806d16c2f8Saliguori } 3281e85d9db5SKevin Wolf /* Avoid unbounded allocations */ 3282e85d9db5SKevin Wolf l = MIN(l, TARGET_PAGE_SIZE); 3283e85d9db5SKevin Wolf bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, l); 32846d16c2f8Saliguori bounce.addr = addr; 32856d16c2f8Saliguori bounce.len = l; 3286d3e71559SPaolo Bonzini 3287d3e71559SPaolo Bonzini memory_region_ref(mr); 3288d3e71559SPaolo Bonzini bounce.mr = mr; 32896d16c2f8Saliguori if (!is_write) { 32905c9eb028SPeter Maydell address_space_read(as, addr, MEMTXATTRS_UNSPECIFIED, 32915c9eb028SPeter Maydell bounce.buffer, l); 32926d16c2f8Saliguori } 329338bee5dcSStefano Stabellini 329441063e1eSPaolo Bonzini rcu_read_unlock(); 329538bee5dcSStefano Stabellini *plen = l; 329638bee5dcSStefano Stabellini return bounce.buffer; 32976d16c2f8Saliguori } 3298e3127ae0SPaolo Bonzini 32996d16c2f8Saliguori 3300d3e71559SPaolo Bonzini memory_region_ref(mr); 3301715c31ecSPaolo Bonzini *plen = address_space_extend_translation(as, addr, len, mr, xlat, l, is_write); 3302715c31ecSPaolo Bonzini ptr = qemu_ram_ptr_length(mr->ram_block, xlat, plen); 3303e81bcda5SPaolo Bonzini rcu_read_unlock(); 3304e81bcda5SPaolo Bonzini 3305e81bcda5SPaolo Bonzini return ptr; 33066d16c2f8Saliguori } 33076d16c2f8Saliguori 3308ac1970fbSAvi Kivity /* Unmaps a memory region previously mapped by address_space_map(). 33096d16c2f8Saliguori * Will also mark the memory as dirty if is_write == 1. access_len gives 33106d16c2f8Saliguori * the amount of memory that was actually read or written by the caller. 33116d16c2f8Saliguori */ 3312a8170e5eSAvi Kivity void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, 3313a8170e5eSAvi Kivity int is_write, hwaddr access_len) 33146d16c2f8Saliguori { 33156d16c2f8Saliguori if (buffer != bounce.buffer) { 3316d3e71559SPaolo Bonzini MemoryRegion *mr; 33177443b437SPaolo Bonzini ram_addr_t addr1; 3318d3e71559SPaolo Bonzini 331907bdaa41SPaolo Bonzini mr = memory_region_from_host(buffer, &addr1); 33201b5ec234SPaolo Bonzini assert(mr != NULL); 3321d3e71559SPaolo Bonzini if (is_write) { 3322845b6214SPaolo Bonzini invalidate_and_set_dirty(mr, addr1, access_len); 33236d16c2f8Saliguori } 3324868bb33fSJan Kiszka if (xen_enabled()) { 3325e41d7c69SJan Kiszka xen_invalidate_map_cache_entry(buffer); 3326050a0ddfSAnthony PERARD } 3327d3e71559SPaolo Bonzini memory_region_unref(mr); 33286d16c2f8Saliguori return; 33296d16c2f8Saliguori } 33306d16c2f8Saliguori if (is_write) { 33315c9eb028SPeter Maydell address_space_write(as, bounce.addr, MEMTXATTRS_UNSPECIFIED, 33325c9eb028SPeter Maydell bounce.buffer, access_len); 33336d16c2f8Saliguori } 3334f8a83245SHerve Poussineau qemu_vfree(bounce.buffer); 33356d16c2f8Saliguori bounce.buffer = NULL; 3336d3e71559SPaolo Bonzini memory_region_unref(bounce.mr); 3337c2cba0ffSFam Zheng atomic_mb_set(&bounce.in_use, false); 3338ba223c29Saliguori cpu_notify_map_clients(); 33396d16c2f8Saliguori } 3340d0ecd2aaSbellard 3341a8170e5eSAvi Kivity void *cpu_physical_memory_map(hwaddr addr, 3342a8170e5eSAvi Kivity hwaddr *plen, 3343ac1970fbSAvi Kivity int is_write) 3344ac1970fbSAvi Kivity { 3345ac1970fbSAvi Kivity return address_space_map(&address_space_memory, addr, plen, is_write); 3346ac1970fbSAvi Kivity } 3347ac1970fbSAvi Kivity 3348a8170e5eSAvi Kivity void cpu_physical_memory_unmap(void *buffer, hwaddr len, 3349a8170e5eSAvi Kivity int is_write, hwaddr access_len) 3350ac1970fbSAvi Kivity { 3351ac1970fbSAvi Kivity return address_space_unmap(&address_space_memory, buffer, len, is_write, access_len); 3352ac1970fbSAvi Kivity } 3353ac1970fbSAvi Kivity 33540ce265ffSPaolo Bonzini #define ARG1_DECL AddressSpace *as 33550ce265ffSPaolo Bonzini #define ARG1 as 33560ce265ffSPaolo Bonzini #define SUFFIX 33570ce265ffSPaolo Bonzini #define TRANSLATE(...) address_space_translate(as, __VA_ARGS__) 33580ce265ffSPaolo Bonzini #define IS_DIRECT(mr, is_write) memory_access_is_direct(mr, is_write) 33590ce265ffSPaolo Bonzini #define MAP_RAM(mr, ofs) qemu_map_ram_ptr((mr)->ram_block, ofs) 33600ce265ffSPaolo Bonzini #define INVALIDATE(mr, ofs, len) invalidate_and_set_dirty(mr, ofs, len) 33610ce265ffSPaolo Bonzini #define RCU_READ_LOCK(...) rcu_read_lock() 33620ce265ffSPaolo Bonzini #define RCU_READ_UNLOCK(...) rcu_read_unlock() 33630ce265ffSPaolo Bonzini #include "memory_ldst.inc.c" 33641e78bcc1SAlexander Graf 33651f4e496eSPaolo Bonzini int64_t address_space_cache_init(MemoryRegionCache *cache, 33661f4e496eSPaolo Bonzini AddressSpace *as, 33671f4e496eSPaolo Bonzini hwaddr addr, 33681f4e496eSPaolo Bonzini hwaddr len, 33691f4e496eSPaolo Bonzini bool is_write) 33701f4e496eSPaolo Bonzini { 337190c4fe5fSPaolo Bonzini cache->len = len; 337290c4fe5fSPaolo Bonzini cache->as = as; 337390c4fe5fSPaolo Bonzini cache->xlat = addr; 337490c4fe5fSPaolo Bonzini return len; 33751f4e496eSPaolo Bonzini } 33761f4e496eSPaolo Bonzini 33771f4e496eSPaolo Bonzini void address_space_cache_invalidate(MemoryRegionCache *cache, 33781f4e496eSPaolo Bonzini hwaddr addr, 33791f4e496eSPaolo Bonzini hwaddr access_len) 33801f4e496eSPaolo Bonzini { 33811f4e496eSPaolo Bonzini } 33821f4e496eSPaolo Bonzini 33831f4e496eSPaolo Bonzini void address_space_cache_destroy(MemoryRegionCache *cache) 33841f4e496eSPaolo Bonzini { 338590c4fe5fSPaolo Bonzini cache->as = NULL; 33861f4e496eSPaolo Bonzini } 33871f4e496eSPaolo Bonzini 33881f4e496eSPaolo Bonzini #define ARG1_DECL MemoryRegionCache *cache 33891f4e496eSPaolo Bonzini #define ARG1 cache 33901f4e496eSPaolo Bonzini #define SUFFIX _cached 339190c4fe5fSPaolo Bonzini #define TRANSLATE(addr, ...) \ 339290c4fe5fSPaolo Bonzini address_space_translate(cache->as, cache->xlat + (addr), __VA_ARGS__) 33931f4e496eSPaolo Bonzini #define IS_DIRECT(mr, is_write) true 339490c4fe5fSPaolo Bonzini #define MAP_RAM(mr, ofs) qemu_map_ram_ptr((mr)->ram_block, ofs) 339590c4fe5fSPaolo Bonzini #define INVALIDATE(mr, ofs, len) invalidate_and_set_dirty(mr, ofs, len) 339690c4fe5fSPaolo Bonzini #define RCU_READ_LOCK() rcu_read_lock() 339790c4fe5fSPaolo Bonzini #define RCU_READ_UNLOCK() rcu_read_unlock() 33981f4e496eSPaolo Bonzini #include "memory_ldst.inc.c" 33991f4e496eSPaolo Bonzini 34005e2972fdSaliguori /* virtual memory access for debug (includes writing to ROM) */ 3401f17ec444SAndreas Färber int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, 3402b448f2f3Sbellard uint8_t *buf, int len, int is_write) 340313eb76e0Sbellard { 340413eb76e0Sbellard int l; 3405a8170e5eSAvi Kivity hwaddr phys_addr; 34069b3c35e0Sj_mayer target_ulong page; 340713eb76e0Sbellard 340879ca7a1bSChristian Borntraeger cpu_synchronize_state(cpu); 340913eb76e0Sbellard while (len > 0) { 34105232e4c7SPeter Maydell int asidx; 34115232e4c7SPeter Maydell MemTxAttrs attrs; 34125232e4c7SPeter Maydell 341313eb76e0Sbellard page = addr & TARGET_PAGE_MASK; 34145232e4c7SPeter Maydell phys_addr = cpu_get_phys_page_attrs_debug(cpu, page, &attrs); 34155232e4c7SPeter Maydell asidx = cpu_asidx_from_attrs(cpu, attrs); 341613eb76e0Sbellard /* if no physical page mapped, return an error */ 341713eb76e0Sbellard if (phys_addr == -1) 341813eb76e0Sbellard return -1; 341913eb76e0Sbellard l = (page + TARGET_PAGE_SIZE) - addr; 342013eb76e0Sbellard if (l > len) 342113eb76e0Sbellard l = len; 34225e2972fdSaliguori phys_addr += (addr & ~TARGET_PAGE_MASK); 34232e38847bSEdgar E. Iglesias if (is_write) { 34245232e4c7SPeter Maydell cpu_physical_memory_write_rom(cpu->cpu_ases[asidx].as, 34255232e4c7SPeter Maydell phys_addr, buf, l); 34262e38847bSEdgar E. Iglesias } else { 34275232e4c7SPeter Maydell address_space_rw(cpu->cpu_ases[asidx].as, phys_addr, 34285232e4c7SPeter Maydell MEMTXATTRS_UNSPECIFIED, 34295c9eb028SPeter Maydell buf, l, 0); 34302e38847bSEdgar E. Iglesias } 343113eb76e0Sbellard len -= l; 343213eb76e0Sbellard buf += l; 343313eb76e0Sbellard addr += l; 343413eb76e0Sbellard } 343513eb76e0Sbellard return 0; 343613eb76e0Sbellard } 3437038629a6SDr. David Alan Gilbert 3438038629a6SDr. David Alan Gilbert /* 3439038629a6SDr. David Alan Gilbert * Allows code that needs to deal with migration bitmaps etc to still be built 3440038629a6SDr. David Alan Gilbert * target independent. 3441038629a6SDr. David Alan Gilbert */ 344220afaed9SJuan Quintela size_t qemu_target_page_size(void) 3443038629a6SDr. David Alan Gilbert { 344420afaed9SJuan Quintela return TARGET_PAGE_SIZE; 3445038629a6SDr. David Alan Gilbert } 3446038629a6SDr. David Alan Gilbert 3447a68fe89cSPaul Brook #endif 344813eb76e0Sbellard 34498e4a424bSBlue Swirl /* 34508e4a424bSBlue Swirl * A helper function for the _utterly broken_ virtio device model to find out if 34518e4a424bSBlue Swirl * it's running on a big endian machine. Don't do this at home kids! 34528e4a424bSBlue Swirl */ 345398ed8ecfSGreg Kurz bool target_words_bigendian(void); 345498ed8ecfSGreg Kurz bool target_words_bigendian(void) 34558e4a424bSBlue Swirl { 34568e4a424bSBlue Swirl #if defined(TARGET_WORDS_BIGENDIAN) 34578e4a424bSBlue Swirl return true; 34588e4a424bSBlue Swirl #else 34598e4a424bSBlue Swirl return false; 34608e4a424bSBlue Swirl #endif 34618e4a424bSBlue Swirl } 34628e4a424bSBlue Swirl 346376f35538SWen Congyang #ifndef CONFIG_USER_ONLY 3464a8170e5eSAvi Kivity bool cpu_physical_memory_is_io(hwaddr phys_addr) 346576f35538SWen Congyang { 34665c8a00ceSPaolo Bonzini MemoryRegion*mr; 3467149f54b5SPaolo Bonzini hwaddr l = 1; 346841063e1eSPaolo Bonzini bool res; 346976f35538SWen Congyang 347041063e1eSPaolo Bonzini rcu_read_lock(); 34715c8a00ceSPaolo Bonzini mr = address_space_translate(&address_space_memory, 3472149f54b5SPaolo Bonzini phys_addr, &phys_addr, &l, false); 347376f35538SWen Congyang 347441063e1eSPaolo Bonzini res = !(memory_region_is_ram(mr) || memory_region_is_romd(mr)); 347541063e1eSPaolo Bonzini rcu_read_unlock(); 347641063e1eSPaolo Bonzini return res; 347776f35538SWen Congyang } 3478bd2fa51fSMichael R. Hines 3479e3807054SDr. David Alan Gilbert int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque) 3480bd2fa51fSMichael R. Hines { 3481bd2fa51fSMichael R. Hines RAMBlock *block; 3482e3807054SDr. David Alan Gilbert int ret = 0; 3483bd2fa51fSMichael R. Hines 34840dc3f44aSMike Day rcu_read_lock(); 348599e15582SPeter Xu RAMBLOCK_FOREACH(block) { 3486e3807054SDr. David Alan Gilbert ret = func(block->idstr, block->host, block->offset, 3487e3807054SDr. David Alan Gilbert block->used_length, opaque); 3488e3807054SDr. David Alan Gilbert if (ret) { 3489e3807054SDr. David Alan Gilbert break; 3490e3807054SDr. David Alan Gilbert } 3491bd2fa51fSMichael R. Hines } 34920dc3f44aSMike Day rcu_read_unlock(); 3493e3807054SDr. David Alan Gilbert return ret; 3494bd2fa51fSMichael R. Hines } 3495d3a5038cSDr. David Alan Gilbert 3496d3a5038cSDr. David Alan Gilbert /* 3497d3a5038cSDr. David Alan Gilbert * Unmap pages of memory from start to start+length such that 3498d3a5038cSDr. David Alan Gilbert * they a) read as 0, b) Trigger whatever fault mechanism 3499d3a5038cSDr. David Alan Gilbert * the OS provides for postcopy. 3500d3a5038cSDr. David Alan Gilbert * The pages must be unmapped by the end of the function. 3501d3a5038cSDr. David Alan Gilbert * Returns: 0 on success, none-0 on failure 3502d3a5038cSDr. David Alan Gilbert * 3503d3a5038cSDr. David Alan Gilbert */ 3504d3a5038cSDr. David Alan Gilbert int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length) 3505d3a5038cSDr. David Alan Gilbert { 3506d3a5038cSDr. David Alan Gilbert int ret = -1; 3507d3a5038cSDr. David Alan Gilbert 3508d3a5038cSDr. David Alan Gilbert uint8_t *host_startaddr = rb->host + start; 3509d3a5038cSDr. David Alan Gilbert 3510d3a5038cSDr. David Alan Gilbert if ((uintptr_t)host_startaddr & (rb->page_size - 1)) { 3511d3a5038cSDr. David Alan Gilbert error_report("ram_block_discard_range: Unaligned start address: %p", 3512d3a5038cSDr. David Alan Gilbert host_startaddr); 3513d3a5038cSDr. David Alan Gilbert goto err; 3514d3a5038cSDr. David Alan Gilbert } 3515d3a5038cSDr. David Alan Gilbert 3516d3a5038cSDr. David Alan Gilbert if ((start + length) <= rb->used_length) { 3517d3a5038cSDr. David Alan Gilbert uint8_t *host_endaddr = host_startaddr + length; 3518d3a5038cSDr. David Alan Gilbert if ((uintptr_t)host_endaddr & (rb->page_size - 1)) { 3519d3a5038cSDr. David Alan Gilbert error_report("ram_block_discard_range: Unaligned end address: %p", 3520d3a5038cSDr. David Alan Gilbert host_endaddr); 3521d3a5038cSDr. David Alan Gilbert goto err; 3522d3a5038cSDr. David Alan Gilbert } 3523d3a5038cSDr. David Alan Gilbert 3524d3a5038cSDr. David Alan Gilbert errno = ENOTSUP; /* If we are missing MADVISE etc */ 3525d3a5038cSDr. David Alan Gilbert 3526e2fa71f5SDr. David Alan Gilbert if (rb->page_size == qemu_host_page_size) { 3527d3a5038cSDr. David Alan Gilbert #if defined(CONFIG_MADVISE) 3528d3a5038cSDr. David Alan Gilbert /* Note: We need the madvise MADV_DONTNEED behaviour of definitely 3529d3a5038cSDr. David Alan Gilbert * freeing the page. 3530d3a5038cSDr. David Alan Gilbert */ 3531d3a5038cSDr. David Alan Gilbert ret = madvise(host_startaddr, length, MADV_DONTNEED); 3532d3a5038cSDr. David Alan Gilbert #endif 3533e2fa71f5SDr. David Alan Gilbert } else { 3534e2fa71f5SDr. David Alan Gilbert /* Huge page case - unfortunately it can't do DONTNEED, but 3535e2fa71f5SDr. David Alan Gilbert * it can do the equivalent by FALLOC_FL_PUNCH_HOLE in the 3536e2fa71f5SDr. David Alan Gilbert * huge page file. 3537e2fa71f5SDr. David Alan Gilbert */ 3538e2fa71f5SDr. David Alan Gilbert #ifdef CONFIG_FALLOCATE_PUNCH_HOLE 3539e2fa71f5SDr. David Alan Gilbert ret = fallocate(rb->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 3540e2fa71f5SDr. David Alan Gilbert start, length); 3541e2fa71f5SDr. David Alan Gilbert #endif 3542e2fa71f5SDr. David Alan Gilbert } 3543d3a5038cSDr. David Alan Gilbert if (ret) { 3544d3a5038cSDr. David Alan Gilbert ret = -errno; 3545d3a5038cSDr. David Alan Gilbert error_report("ram_block_discard_range: Failed to discard range " 3546d3a5038cSDr. David Alan Gilbert "%s:%" PRIx64 " +%zx (%d)", 3547d3a5038cSDr. David Alan Gilbert rb->idstr, start, length, ret); 3548d3a5038cSDr. David Alan Gilbert } 3549d3a5038cSDr. David Alan Gilbert } else { 3550d3a5038cSDr. David Alan Gilbert error_report("ram_block_discard_range: Overrun block '%s' (%" PRIu64 3551d3a5038cSDr. David Alan Gilbert "/%zx/" RAM_ADDR_FMT")", 3552d3a5038cSDr. David Alan Gilbert rb->idstr, start, length, rb->used_length); 3553d3a5038cSDr. David Alan Gilbert } 3554d3a5038cSDr. David Alan Gilbert 3555d3a5038cSDr. David Alan Gilbert err: 3556d3a5038cSDr. David Alan Gilbert return ret; 3557d3a5038cSDr. David Alan Gilbert } 3558d3a5038cSDr. David Alan Gilbert 3559ec3f8c99SPeter Maydell #endif 3560