1df4fd7d5SPhilippe Mathieu-Daudé /* 232cad1ffSPhilippe Mathieu-Daudé * QEMU CPU model (system specific) 3df4fd7d5SPhilippe Mathieu-Daudé * 4df4fd7d5SPhilippe Mathieu-Daudé * Copyright (c) 2012-2014 SUSE LINUX Products GmbH 5df4fd7d5SPhilippe Mathieu-Daudé * 6df4fd7d5SPhilippe Mathieu-Daudé * This program is free software; you can redistribute it and/or 7df4fd7d5SPhilippe Mathieu-Daudé * modify it under the terms of the GNU General Public License 8df4fd7d5SPhilippe Mathieu-Daudé * as published by the Free Software Foundation; either version 2 9df4fd7d5SPhilippe Mathieu-Daudé * of the License, or (at your option) any later version. 10df4fd7d5SPhilippe Mathieu-Daudé * 11df4fd7d5SPhilippe Mathieu-Daudé * This program is distributed in the hope that it will be useful, 12df4fd7d5SPhilippe Mathieu-Daudé * but WITHOUT ANY WARRANTY; without even the implied warranty of 13df4fd7d5SPhilippe Mathieu-Daudé * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14df4fd7d5SPhilippe Mathieu-Daudé * GNU General Public License for more details. 15df4fd7d5SPhilippe Mathieu-Daudé * 16df4fd7d5SPhilippe Mathieu-Daudé * You should have received a copy of the GNU General Public License 17df4fd7d5SPhilippe Mathieu-Daudé * along with this program; if not, see 18df4fd7d5SPhilippe Mathieu-Daudé * <http://www.gnu.org/licenses/gpl-2.0.html> 19df4fd7d5SPhilippe Mathieu-Daudé */ 20df4fd7d5SPhilippe Mathieu-Daudé 21df4fd7d5SPhilippe Mathieu-Daudé #include "qemu/osdep.h" 22df4fd7d5SPhilippe Mathieu-Daudé #include "qapi/error.h" 23*a86cf967SPhilippe Mathieu-Daudé #include "exec/address-spaces.h" 24e3a575f5SPhilippe Mathieu-Daudé #include "exec/memory.h" 2542508261SPhilippe Mathieu-Daudé #include "exec/tswap.h" 26e3a575f5SPhilippe Mathieu-Daudé #include "hw/qdev-core.h" 27e3a575f5SPhilippe Mathieu-Daudé #include "hw/qdev-properties.h" 28da383e02SPhilippe Mathieu-Daudé #include "hw/core/sysemu-cpu-ops.h" 29df4fd7d5SPhilippe Mathieu-Daudé 3077ba5d50SPhilippe Mathieu-Daudé bool cpu_paging_enabled(const CPUState *cpu) 3177ba5d50SPhilippe Mathieu-Daudé { 3277ba5d50SPhilippe Mathieu-Daudé CPUClass *cc = CPU_GET_CLASS(cpu); 3377ba5d50SPhilippe Mathieu-Daudé 346bc0d6a0SPhilippe Mathieu-Daudé if (cc->sysemu_ops->get_paging_enabled) { 356bc0d6a0SPhilippe Mathieu-Daudé return cc->sysemu_ops->get_paging_enabled(cpu); 3677ba5d50SPhilippe Mathieu-Daudé } 3777ba5d50SPhilippe Mathieu-Daudé 3877ba5d50SPhilippe Mathieu-Daudé return false; 3977ba5d50SPhilippe Mathieu-Daudé } 4077ba5d50SPhilippe Mathieu-Daudé 418a5b974bSMarc-André Lureau bool cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list, 4265c57115SPhilippe Mathieu-Daudé Error **errp) 4365c57115SPhilippe Mathieu-Daudé { 4465c57115SPhilippe Mathieu-Daudé CPUClass *cc = CPU_GET_CLASS(cpu); 4565c57115SPhilippe Mathieu-Daudé 462b60b62eSPhilippe Mathieu-Daudé if (cc->sysemu_ops->get_memory_mapping) { 478a5b974bSMarc-André Lureau return cc->sysemu_ops->get_memory_mapping(cpu, list, errp); 4865c57115SPhilippe Mathieu-Daudé } 4965c57115SPhilippe Mathieu-Daudé 5065c57115SPhilippe Mathieu-Daudé error_setg(errp, "Obtaining memory mappings is unsupported on this CPU."); 518a5b974bSMarc-André Lureau return false; 5265c57115SPhilippe Mathieu-Daudé } 5365c57115SPhilippe Mathieu-Daudé 54a41d3aaeSPhilippe Mathieu-Daudé hwaddr cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr, 55a41d3aaeSPhilippe Mathieu-Daudé MemTxAttrs *attrs) 56a41d3aaeSPhilippe Mathieu-Daudé { 57a41d3aaeSPhilippe Mathieu-Daudé CPUClass *cc = CPU_GET_CLASS(cpu); 581cceedd7SDavid Hildenbrand hwaddr paddr; 59a41d3aaeSPhilippe Mathieu-Daudé 6008928c6dSPhilippe Mathieu-Daudé if (cc->sysemu_ops->get_phys_page_attrs_debug) { 611cceedd7SDavid Hildenbrand paddr = cc->sysemu_ops->get_phys_page_attrs_debug(cpu, addr, attrs); 621cceedd7SDavid Hildenbrand } else { 63a41d3aaeSPhilippe Mathieu-Daudé /* Fallback for CPUs which don't implement the _attrs_ hook */ 64a41d3aaeSPhilippe Mathieu-Daudé *attrs = MEMTXATTRS_UNSPECIFIED; 651cceedd7SDavid Hildenbrand paddr = cc->sysemu_ops->get_phys_page_debug(cpu, addr); 661cceedd7SDavid Hildenbrand } 671cceedd7SDavid Hildenbrand /* Indicate that this is a debug access. */ 681cceedd7SDavid Hildenbrand attrs->debug = 1; 691cceedd7SDavid Hildenbrand return paddr; 70a41d3aaeSPhilippe Mathieu-Daudé } 71a41d3aaeSPhilippe Mathieu-Daudé 72a41d3aaeSPhilippe Mathieu-Daudé hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr) 73a41d3aaeSPhilippe Mathieu-Daudé { 74a41d3aaeSPhilippe Mathieu-Daudé MemTxAttrs attrs = {}; 75a41d3aaeSPhilippe Mathieu-Daudé 76a41d3aaeSPhilippe Mathieu-Daudé return cpu_get_phys_page_attrs_debug(cpu, addr, &attrs); 77a41d3aaeSPhilippe Mathieu-Daudé } 78a41d3aaeSPhilippe Mathieu-Daudé 79a41d3aaeSPhilippe Mathieu-Daudé int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs) 80a41d3aaeSPhilippe Mathieu-Daudé { 81a41d3aaeSPhilippe Mathieu-Daudé int ret = 0; 82a41d3aaeSPhilippe Mathieu-Daudé 83b404ca37SAlex Bennée if (cpu->cc->sysemu_ops->asidx_from_attrs) { 84b404ca37SAlex Bennée ret = cpu->cc->sysemu_ops->asidx_from_attrs(cpu, attrs); 85a41d3aaeSPhilippe Mathieu-Daudé assert(ret < cpu->num_ases && ret >= 0); 86a41d3aaeSPhilippe Mathieu-Daudé } 87a41d3aaeSPhilippe Mathieu-Daudé return ret; 88a41d3aaeSPhilippe Mathieu-Daudé } 89a41d3aaeSPhilippe Mathieu-Daudé 905ef2d5a4SPhilippe Mathieu-Daudé int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu, 915ef2d5a4SPhilippe Mathieu-Daudé void *opaque) 925ef2d5a4SPhilippe Mathieu-Daudé { 935ef2d5a4SPhilippe Mathieu-Daudé CPUClass *cc = CPU_GET_CLASS(cpu); 945ef2d5a4SPhilippe Mathieu-Daudé 95715e3c1aSPhilippe Mathieu-Daudé if (!cc->sysemu_ops->write_elf32_qemunote) { 965ef2d5a4SPhilippe Mathieu-Daudé return 0; 975ef2d5a4SPhilippe Mathieu-Daudé } 98715e3c1aSPhilippe Mathieu-Daudé return (*cc->sysemu_ops->write_elf32_qemunote)(f, cpu, opaque); 995ef2d5a4SPhilippe Mathieu-Daudé } 1005ef2d5a4SPhilippe Mathieu-Daudé 1015ef2d5a4SPhilippe Mathieu-Daudé int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu, 1025ef2d5a4SPhilippe Mathieu-Daudé int cpuid, void *opaque) 1035ef2d5a4SPhilippe Mathieu-Daudé { 1045ef2d5a4SPhilippe Mathieu-Daudé CPUClass *cc = CPU_GET_CLASS(cpu); 1055ef2d5a4SPhilippe Mathieu-Daudé 106715e3c1aSPhilippe Mathieu-Daudé if (!cc->sysemu_ops->write_elf32_note) { 1075ef2d5a4SPhilippe Mathieu-Daudé return -1; 1085ef2d5a4SPhilippe Mathieu-Daudé } 109715e3c1aSPhilippe Mathieu-Daudé return (*cc->sysemu_ops->write_elf32_note)(f, cpu, cpuid, opaque); 1105ef2d5a4SPhilippe Mathieu-Daudé } 1115ef2d5a4SPhilippe Mathieu-Daudé 1125ef2d5a4SPhilippe Mathieu-Daudé int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu, 1135ef2d5a4SPhilippe Mathieu-Daudé void *opaque) 1145ef2d5a4SPhilippe Mathieu-Daudé { 1155ef2d5a4SPhilippe Mathieu-Daudé CPUClass *cc = CPU_GET_CLASS(cpu); 1165ef2d5a4SPhilippe Mathieu-Daudé 117715e3c1aSPhilippe Mathieu-Daudé if (!cc->sysemu_ops->write_elf64_qemunote) { 1185ef2d5a4SPhilippe Mathieu-Daudé return 0; 1195ef2d5a4SPhilippe Mathieu-Daudé } 120715e3c1aSPhilippe Mathieu-Daudé return (*cc->sysemu_ops->write_elf64_qemunote)(f, cpu, opaque); 1215ef2d5a4SPhilippe Mathieu-Daudé } 1225ef2d5a4SPhilippe Mathieu-Daudé 1235ef2d5a4SPhilippe Mathieu-Daudé int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu, 1245ef2d5a4SPhilippe Mathieu-Daudé int cpuid, void *opaque) 1255ef2d5a4SPhilippe Mathieu-Daudé { 1265ef2d5a4SPhilippe Mathieu-Daudé CPUClass *cc = CPU_GET_CLASS(cpu); 1275ef2d5a4SPhilippe Mathieu-Daudé 128715e3c1aSPhilippe Mathieu-Daudé if (!cc->sysemu_ops->write_elf64_note) { 1295ef2d5a4SPhilippe Mathieu-Daudé return -1; 1305ef2d5a4SPhilippe Mathieu-Daudé } 131715e3c1aSPhilippe Mathieu-Daudé return (*cc->sysemu_ops->write_elf64_note)(f, cpu, cpuid, opaque); 1325ef2d5a4SPhilippe Mathieu-Daudé } 1335ef2d5a4SPhilippe Mathieu-Daudé 134cdba7e2fSPhilippe Mathieu-Daudé bool cpu_virtio_is_big_endian(CPUState *cpu) 135cdba7e2fSPhilippe Mathieu-Daudé { 136cdba7e2fSPhilippe Mathieu-Daudé CPUClass *cc = CPU_GET_CLASS(cpu); 137cdba7e2fSPhilippe Mathieu-Daudé 138da383e02SPhilippe Mathieu-Daudé if (cc->sysemu_ops->virtio_is_big_endian) { 139da383e02SPhilippe Mathieu-Daudé return cc->sysemu_ops->virtio_is_big_endian(cpu); 140cdba7e2fSPhilippe Mathieu-Daudé } 141cdba7e2fSPhilippe Mathieu-Daudé return target_words_bigendian(); 142cdba7e2fSPhilippe Mathieu-Daudé } 143cdba7e2fSPhilippe Mathieu-Daudé 144df4fd7d5SPhilippe Mathieu-Daudé GuestPanicInformation *cpu_get_crash_info(CPUState *cpu) 145df4fd7d5SPhilippe Mathieu-Daudé { 146df4fd7d5SPhilippe Mathieu-Daudé CPUClass *cc = CPU_GET_CLASS(cpu); 147df4fd7d5SPhilippe Mathieu-Daudé GuestPanicInformation *res = NULL; 148df4fd7d5SPhilippe Mathieu-Daudé 14983ec01b6SPhilippe Mathieu-Daudé if (cc->sysemu_ops->get_crash_info) { 15083ec01b6SPhilippe Mathieu-Daudé res = cc->sysemu_ops->get_crash_info(cpu); 151df4fd7d5SPhilippe Mathieu-Daudé } 152df4fd7d5SPhilippe Mathieu-Daudé return res; 153df4fd7d5SPhilippe Mathieu-Daudé } 154e3a575f5SPhilippe Mathieu-Daudé 155e3a575f5SPhilippe Mathieu-Daudé static const Property cpu_system_props[] = { 156e3a575f5SPhilippe Mathieu-Daudé /* 157e3a575f5SPhilippe Mathieu-Daudé * Create a memory property for system CPU object, so users can 158e3a575f5SPhilippe Mathieu-Daudé * wire up its memory. The default if no link is set up is to use 159e3a575f5SPhilippe Mathieu-Daudé * the system address space. 160e3a575f5SPhilippe Mathieu-Daudé */ 161e3a575f5SPhilippe Mathieu-Daudé DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION, 162e3a575f5SPhilippe Mathieu-Daudé MemoryRegion *), 163e3a575f5SPhilippe Mathieu-Daudé }; 164e3a575f5SPhilippe Mathieu-Daudé 165e3a575f5SPhilippe Mathieu-Daudé static bool cpu_get_start_powered_off(Object *obj, Error **errp) 166e3a575f5SPhilippe Mathieu-Daudé { 167e3a575f5SPhilippe Mathieu-Daudé CPUState *cpu = CPU(obj); 168e3a575f5SPhilippe Mathieu-Daudé return cpu->start_powered_off; 169e3a575f5SPhilippe Mathieu-Daudé } 170e3a575f5SPhilippe Mathieu-Daudé 171e3a575f5SPhilippe Mathieu-Daudé static void cpu_set_start_powered_off(Object *obj, bool value, Error **errp) 172e3a575f5SPhilippe Mathieu-Daudé { 173e3a575f5SPhilippe Mathieu-Daudé CPUState *cpu = CPU(obj); 174e3a575f5SPhilippe Mathieu-Daudé cpu->start_powered_off = value; 175e3a575f5SPhilippe Mathieu-Daudé } 176e3a575f5SPhilippe Mathieu-Daudé 177e3a575f5SPhilippe Mathieu-Daudé void cpu_class_init_props(DeviceClass *dc) 178e3a575f5SPhilippe Mathieu-Daudé { 179e3a575f5SPhilippe Mathieu-Daudé ObjectClass *oc = OBJECT_CLASS(dc); 180e3a575f5SPhilippe Mathieu-Daudé 181e3a575f5SPhilippe Mathieu-Daudé /* 182e3a575f5SPhilippe Mathieu-Daudé * We can't use DEFINE_PROP_BOOL in the Property array for this 183e3a575f5SPhilippe Mathieu-Daudé * property, because we want this to be settable after realize. 184e3a575f5SPhilippe Mathieu-Daudé */ 185e3a575f5SPhilippe Mathieu-Daudé object_class_property_add_bool(oc, "start-powered-off", 186e3a575f5SPhilippe Mathieu-Daudé cpu_get_start_powered_off, 187e3a575f5SPhilippe Mathieu-Daudé cpu_set_start_powered_off); 188e3a575f5SPhilippe Mathieu-Daudé 189e3a575f5SPhilippe Mathieu-Daudé device_class_set_props(dc, cpu_system_props); 190e3a575f5SPhilippe Mathieu-Daudé } 191*a86cf967SPhilippe Mathieu-Daudé 192*a86cf967SPhilippe Mathieu-Daudé void cpu_exec_initfn(CPUState *cpu) 193*a86cf967SPhilippe Mathieu-Daudé { 194*a86cf967SPhilippe Mathieu-Daudé cpu->memory = get_system_memory(); 195*a86cf967SPhilippe Mathieu-Daudé object_ref(OBJECT(cpu->memory)); 196*a86cf967SPhilippe Mathieu-Daudé } 197