1fcf5ef2aSThomas Huth /* 2fcf5ef2aSThomas Huth * ARM implementation of KVM hooks 3fcf5ef2aSThomas Huth * 4fcf5ef2aSThomas Huth * Copyright Christoffer Dall 2009-2010 5fcf5ef2aSThomas Huth * 6fcf5ef2aSThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 or later. 7fcf5ef2aSThomas Huth * See the COPYING file in the top-level directory. 8fcf5ef2aSThomas Huth * 9fcf5ef2aSThomas Huth */ 10fcf5ef2aSThomas Huth 11fcf5ef2aSThomas Huth #include "qemu/osdep.h" 12fcf5ef2aSThomas Huth #include <sys/ioctl.h> 13fcf5ef2aSThomas Huth 14fcf5ef2aSThomas Huth #include <linux/kvm.h> 15fcf5ef2aSThomas Huth 16fcf5ef2aSThomas Huth #include "qemu-common.h" 17fcf5ef2aSThomas Huth #include "qemu/timer.h" 18fcf5ef2aSThomas Huth #include "qemu/error-report.h" 19db725815SMarkus Armbruster #include "qemu/main-loop.h" 20dea101a1SAndrew Jones #include "qom/object.h" 21dea101a1SAndrew Jones #include "qapi/error.h" 22fcf5ef2aSThomas Huth #include "sysemu/sysemu.h" 23fcf5ef2aSThomas Huth #include "sysemu/kvm.h" 24a27382e2SEric Auger #include "sysemu/kvm_int.h" 25fcf5ef2aSThomas Huth #include "kvm_arm.h" 26fcf5ef2aSThomas Huth #include "cpu.h" 27b05c81d2SEric Auger #include "trace.h" 28fcf5ef2aSThomas Huth #include "internals.h" 29b05c81d2SEric Auger #include "hw/pci/pci.h" 30fcf5ef2aSThomas Huth #include "exec/memattrs.h" 31fcf5ef2aSThomas Huth #include "exec/address-spaces.h" 32fcf5ef2aSThomas Huth #include "hw/boards.h" 3364552b6bSMarkus Armbruster #include "hw/irq.h" 34fcf5ef2aSThomas Huth #include "qemu/log.h" 35fcf5ef2aSThomas Huth 36fcf5ef2aSThomas Huth const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 37fcf5ef2aSThomas Huth KVM_CAP_LAST_INFO 38fcf5ef2aSThomas Huth }; 39fcf5ef2aSThomas Huth 40fcf5ef2aSThomas Huth static bool cap_has_mp_state; 41202ccb6bSDongjiu Geng static bool cap_has_inject_serror_esr; 42fcf5ef2aSThomas Huth 43c4487d76SPeter Maydell static ARMHostCPUFeatures arm_host_cpu_features; 44c4487d76SPeter Maydell 45fcf5ef2aSThomas Huth int kvm_arm_vcpu_init(CPUState *cs) 46fcf5ef2aSThomas Huth { 47fcf5ef2aSThomas Huth ARMCPU *cpu = ARM_CPU(cs); 48fcf5ef2aSThomas Huth struct kvm_vcpu_init init; 49fcf5ef2aSThomas Huth 50fcf5ef2aSThomas Huth init.target = cpu->kvm_target; 51fcf5ef2aSThomas Huth memcpy(init.features, cpu->kvm_init_features, sizeof(init.features)); 52fcf5ef2aSThomas Huth 53fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init); 54fcf5ef2aSThomas Huth } 55fcf5ef2aSThomas Huth 5614e99e0fSAndrew Jones int kvm_arm_vcpu_finalize(CPUState *cs, int feature) 5714e99e0fSAndrew Jones { 5814e99e0fSAndrew Jones return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_FINALIZE, &feature); 5914e99e0fSAndrew Jones } 6014e99e0fSAndrew Jones 61202ccb6bSDongjiu Geng void kvm_arm_init_serror_injection(CPUState *cs) 62202ccb6bSDongjiu Geng { 63202ccb6bSDongjiu Geng cap_has_inject_serror_esr = kvm_check_extension(cs->kvm_state, 64202ccb6bSDongjiu Geng KVM_CAP_ARM_INJECT_SERROR_ESR); 65202ccb6bSDongjiu Geng } 66202ccb6bSDongjiu Geng 67fcf5ef2aSThomas Huth bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try, 68fcf5ef2aSThomas Huth int *fdarray, 69fcf5ef2aSThomas Huth struct kvm_vcpu_init *init) 70fcf5ef2aSThomas Huth { 710cdb4020SAndrew Jones int ret = 0, kvmfd = -1, vmfd = -1, cpufd = -1; 72fcf5ef2aSThomas Huth 73fcf5ef2aSThomas Huth kvmfd = qemu_open("/dev/kvm", O_RDWR); 74fcf5ef2aSThomas Huth if (kvmfd < 0) { 75fcf5ef2aSThomas Huth goto err; 76fcf5ef2aSThomas Huth } 77fcf5ef2aSThomas Huth vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0); 78fcf5ef2aSThomas Huth if (vmfd < 0) { 79fcf5ef2aSThomas Huth goto err; 80fcf5ef2aSThomas Huth } 81fcf5ef2aSThomas Huth cpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0); 82fcf5ef2aSThomas Huth if (cpufd < 0) { 83fcf5ef2aSThomas Huth goto err; 84fcf5ef2aSThomas Huth } 85fcf5ef2aSThomas Huth 86fcf5ef2aSThomas Huth if (!init) { 87fcf5ef2aSThomas Huth /* Caller doesn't want the VCPU to be initialized, so skip it */ 88fcf5ef2aSThomas Huth goto finish; 89fcf5ef2aSThomas Huth } 90fcf5ef2aSThomas Huth 910cdb4020SAndrew Jones if (init->target == -1) { 920cdb4020SAndrew Jones struct kvm_vcpu_init preferred; 930cdb4020SAndrew Jones 940cdb4020SAndrew Jones ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, &preferred); 950cdb4020SAndrew Jones if (!ret) { 960cdb4020SAndrew Jones init->target = preferred.target; 970cdb4020SAndrew Jones } 980cdb4020SAndrew Jones } 99fcf5ef2aSThomas Huth if (ret >= 0) { 100fcf5ef2aSThomas Huth ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, init); 101fcf5ef2aSThomas Huth if (ret < 0) { 102fcf5ef2aSThomas Huth goto err; 103fcf5ef2aSThomas Huth } 104fcf5ef2aSThomas Huth } else if (cpus_to_try) { 105fcf5ef2aSThomas Huth /* Old kernel which doesn't know about the 106fcf5ef2aSThomas Huth * PREFERRED_TARGET ioctl: we know it will only support 107fcf5ef2aSThomas Huth * creating one kind of guest CPU which is its preferred 108fcf5ef2aSThomas Huth * CPU type. 109fcf5ef2aSThomas Huth */ 1100cdb4020SAndrew Jones struct kvm_vcpu_init try; 1110cdb4020SAndrew Jones 112fcf5ef2aSThomas Huth while (*cpus_to_try != QEMU_KVM_ARM_TARGET_NONE) { 1130cdb4020SAndrew Jones try.target = *cpus_to_try++; 1140cdb4020SAndrew Jones memcpy(try.features, init->features, sizeof(init->features)); 1150cdb4020SAndrew Jones ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, &try); 116fcf5ef2aSThomas Huth if (ret >= 0) { 117fcf5ef2aSThomas Huth break; 118fcf5ef2aSThomas Huth } 119fcf5ef2aSThomas Huth } 120fcf5ef2aSThomas Huth if (ret < 0) { 121fcf5ef2aSThomas Huth goto err; 122fcf5ef2aSThomas Huth } 1230cdb4020SAndrew Jones init->target = try.target; 124fcf5ef2aSThomas Huth } else { 125fcf5ef2aSThomas Huth /* Treat a NULL cpus_to_try argument the same as an empty 126fcf5ef2aSThomas Huth * list, which means we will fail the call since this must 127fcf5ef2aSThomas Huth * be an old kernel which doesn't support PREFERRED_TARGET. 128fcf5ef2aSThomas Huth */ 129fcf5ef2aSThomas Huth goto err; 130fcf5ef2aSThomas Huth } 131fcf5ef2aSThomas Huth 132fcf5ef2aSThomas Huth finish: 133fcf5ef2aSThomas Huth fdarray[0] = kvmfd; 134fcf5ef2aSThomas Huth fdarray[1] = vmfd; 135fcf5ef2aSThomas Huth fdarray[2] = cpufd; 136fcf5ef2aSThomas Huth 137fcf5ef2aSThomas Huth return true; 138fcf5ef2aSThomas Huth 139fcf5ef2aSThomas Huth err: 140fcf5ef2aSThomas Huth if (cpufd >= 0) { 141fcf5ef2aSThomas Huth close(cpufd); 142fcf5ef2aSThomas Huth } 143fcf5ef2aSThomas Huth if (vmfd >= 0) { 144fcf5ef2aSThomas Huth close(vmfd); 145fcf5ef2aSThomas Huth } 146fcf5ef2aSThomas Huth if (kvmfd >= 0) { 147fcf5ef2aSThomas Huth close(kvmfd); 148fcf5ef2aSThomas Huth } 149fcf5ef2aSThomas Huth 150fcf5ef2aSThomas Huth return false; 151fcf5ef2aSThomas Huth } 152fcf5ef2aSThomas Huth 153fcf5ef2aSThomas Huth void kvm_arm_destroy_scratch_host_vcpu(int *fdarray) 154fcf5ef2aSThomas Huth { 155fcf5ef2aSThomas Huth int i; 156fcf5ef2aSThomas Huth 157fcf5ef2aSThomas Huth for (i = 2; i >= 0; i--) { 158fcf5ef2aSThomas Huth close(fdarray[i]); 159fcf5ef2aSThomas Huth } 160fcf5ef2aSThomas Huth } 161fcf5ef2aSThomas Huth 162c4487d76SPeter Maydell void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) 163fcf5ef2aSThomas Huth { 164c4487d76SPeter Maydell CPUARMState *env = &cpu->env; 165fcf5ef2aSThomas Huth 166c4487d76SPeter Maydell if (!arm_host_cpu_features.dtb_compatible) { 167c4487d76SPeter Maydell if (!kvm_enabled() || 168c4487d76SPeter Maydell !kvm_arm_get_host_cpu_features(&arm_host_cpu_features)) { 169c4487d76SPeter Maydell /* We can't report this error yet, so flag that we need to 170c4487d76SPeter Maydell * in arm_cpu_realizefn(). 171fcf5ef2aSThomas Huth */ 172c4487d76SPeter Maydell cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE; 173c4487d76SPeter Maydell cpu->host_cpu_probe_failed = true; 174c4487d76SPeter Maydell return; 175fcf5ef2aSThomas Huth } 176fcf5ef2aSThomas Huth } 177fcf5ef2aSThomas Huth 178c4487d76SPeter Maydell cpu->kvm_target = arm_host_cpu_features.target; 179c4487d76SPeter Maydell cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible; 1804674097cSRichard Henderson cpu->isar = arm_host_cpu_features.isar; 181c4487d76SPeter Maydell env->features = arm_host_cpu_features.features; 182c4487d76SPeter Maydell } 183c4487d76SPeter Maydell 184dea101a1SAndrew Jones static bool kvm_no_adjvtime_get(Object *obj, Error **errp) 185dea101a1SAndrew Jones { 186dea101a1SAndrew Jones return !ARM_CPU(obj)->kvm_adjvtime; 187dea101a1SAndrew Jones } 188dea101a1SAndrew Jones 189dea101a1SAndrew Jones static void kvm_no_adjvtime_set(Object *obj, bool value, Error **errp) 190dea101a1SAndrew Jones { 191dea101a1SAndrew Jones ARM_CPU(obj)->kvm_adjvtime = !value; 192dea101a1SAndrew Jones } 193dea101a1SAndrew Jones 194dea101a1SAndrew Jones /* KVM VCPU properties should be prefixed with "kvm-". */ 195dea101a1SAndrew Jones void kvm_arm_add_vcpu_properties(Object *obj) 196dea101a1SAndrew Jones { 197dea101a1SAndrew Jones if (!kvm_enabled()) { 198dea101a1SAndrew Jones return; 199dea101a1SAndrew Jones } 200dea101a1SAndrew Jones 201dea101a1SAndrew Jones ARM_CPU(obj)->kvm_adjvtime = true; 202dea101a1SAndrew Jones object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get, 203*d2623129SMarkus Armbruster kvm_no_adjvtime_set); 204dea101a1SAndrew Jones object_property_set_description(obj, "kvm-no-adjvtime", 205dea101a1SAndrew Jones "Set on to disable the adjustment of " 206dea101a1SAndrew Jones "the virtual counter. VM stopped time " 2077eecec7dSMarkus Armbruster "will be counted."); 208dea101a1SAndrew Jones } 209dea101a1SAndrew Jones 210ae502508SAndrew Jones bool kvm_arm_pmu_supported(CPUState *cpu) 211ae502508SAndrew Jones { 212d70c996dSPhilippe Mathieu-Daudé return kvm_check_extension(cpu->kvm_state, KVM_CAP_ARM_PMU_V3); 213ae502508SAndrew Jones } 214ae502508SAndrew Jones 215a27382e2SEric Auger int kvm_arm_get_max_vm_ipa_size(MachineState *ms) 216a27382e2SEric Auger { 217a27382e2SEric Auger KVMState *s = KVM_STATE(ms->accelerator); 218a27382e2SEric Auger int ret; 219a27382e2SEric Auger 220a27382e2SEric Auger ret = kvm_check_extension(s, KVM_CAP_ARM_VM_IPA_SIZE); 221a27382e2SEric Auger return ret > 0 ? ret : 40; 222a27382e2SEric Auger } 223a27382e2SEric Auger 224fcf5ef2aSThomas Huth int kvm_arch_init(MachineState *ms, KVMState *s) 225fcf5ef2aSThomas Huth { 226fff9f555SEric Auger int ret = 0; 227fcf5ef2aSThomas Huth /* For ARM interrupt delivery is always asynchronous, 228fcf5ef2aSThomas Huth * whether we are using an in-kernel VGIC or not. 229fcf5ef2aSThomas Huth */ 230fcf5ef2aSThomas Huth kvm_async_interrupts_allowed = true; 231fcf5ef2aSThomas Huth 2325d721b78SAlexander Graf /* 2335d721b78SAlexander Graf * PSCI wakes up secondary cores, so we always need to 2345d721b78SAlexander Graf * have vCPUs waiting in kernel space 2355d721b78SAlexander Graf */ 2365d721b78SAlexander Graf kvm_halt_in_kernel_allowed = true; 2375d721b78SAlexander Graf 238fcf5ef2aSThomas Huth cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); 239fcf5ef2aSThomas Huth 240fff9f555SEric Auger if (ms->smp.cpus > 256 && 241fff9f555SEric Auger !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) { 242fff9f555SEric Auger error_report("Using more than 256 vcpus requires a host kernel " 243fff9f555SEric Auger "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2"); 244fff9f555SEric Auger ret = -EINVAL; 245fff9f555SEric Auger } 246fff9f555SEric Auger 247fff9f555SEric Auger return ret; 248fcf5ef2aSThomas Huth } 249fcf5ef2aSThomas Huth 250fcf5ef2aSThomas Huth unsigned long kvm_arch_vcpu_id(CPUState *cpu) 251fcf5ef2aSThomas Huth { 252fcf5ef2aSThomas Huth return cpu->cpu_index; 253fcf5ef2aSThomas Huth } 254fcf5ef2aSThomas Huth 255fcf5ef2aSThomas Huth /* We track all the KVM devices which need their memory addresses 256fcf5ef2aSThomas Huth * passing to the kernel in a list of these structures. 257fcf5ef2aSThomas Huth * When board init is complete we run through the list and 258fcf5ef2aSThomas Huth * tell the kernel the base addresses of the memory regions. 259fcf5ef2aSThomas Huth * We use a MemoryListener to track mapping and unmapping of 260fcf5ef2aSThomas Huth * the regions during board creation, so the board models don't 261fcf5ef2aSThomas Huth * need to do anything special for the KVM case. 26219d1bd0bSEric Auger * 26319d1bd0bSEric Auger * Sometimes the address must be OR'ed with some other fields 26419d1bd0bSEric Auger * (for example for KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION). 26519d1bd0bSEric Auger * @kda_addr_ormask aims at storing the value of those fields. 266fcf5ef2aSThomas Huth */ 267fcf5ef2aSThomas Huth typedef struct KVMDevice { 268fcf5ef2aSThomas Huth struct kvm_arm_device_addr kda; 269fcf5ef2aSThomas Huth struct kvm_device_attr kdattr; 27019d1bd0bSEric Auger uint64_t kda_addr_ormask; 271fcf5ef2aSThomas Huth MemoryRegion *mr; 272fcf5ef2aSThomas Huth QSLIST_ENTRY(KVMDevice) entries; 273fcf5ef2aSThomas Huth int dev_fd; 274fcf5ef2aSThomas Huth } KVMDevice; 275fcf5ef2aSThomas Huth 276b58deb34SPaolo Bonzini static QSLIST_HEAD(, KVMDevice) kvm_devices_head; 277fcf5ef2aSThomas Huth 278fcf5ef2aSThomas Huth static void kvm_arm_devlistener_add(MemoryListener *listener, 279fcf5ef2aSThomas Huth MemoryRegionSection *section) 280fcf5ef2aSThomas Huth { 281fcf5ef2aSThomas Huth KVMDevice *kd; 282fcf5ef2aSThomas Huth 283fcf5ef2aSThomas Huth QSLIST_FOREACH(kd, &kvm_devices_head, entries) { 284fcf5ef2aSThomas Huth if (section->mr == kd->mr) { 285fcf5ef2aSThomas Huth kd->kda.addr = section->offset_within_address_space; 286fcf5ef2aSThomas Huth } 287fcf5ef2aSThomas Huth } 288fcf5ef2aSThomas Huth } 289fcf5ef2aSThomas Huth 290fcf5ef2aSThomas Huth static void kvm_arm_devlistener_del(MemoryListener *listener, 291fcf5ef2aSThomas Huth MemoryRegionSection *section) 292fcf5ef2aSThomas Huth { 293fcf5ef2aSThomas Huth KVMDevice *kd; 294fcf5ef2aSThomas Huth 295fcf5ef2aSThomas Huth QSLIST_FOREACH(kd, &kvm_devices_head, entries) { 296fcf5ef2aSThomas Huth if (section->mr == kd->mr) { 297fcf5ef2aSThomas Huth kd->kda.addr = -1; 298fcf5ef2aSThomas Huth } 299fcf5ef2aSThomas Huth } 300fcf5ef2aSThomas Huth } 301fcf5ef2aSThomas Huth 302fcf5ef2aSThomas Huth static MemoryListener devlistener = { 303fcf5ef2aSThomas Huth .region_add = kvm_arm_devlistener_add, 304fcf5ef2aSThomas Huth .region_del = kvm_arm_devlistener_del, 305fcf5ef2aSThomas Huth }; 306fcf5ef2aSThomas Huth 307fcf5ef2aSThomas Huth static void kvm_arm_set_device_addr(KVMDevice *kd) 308fcf5ef2aSThomas Huth { 309fcf5ef2aSThomas Huth struct kvm_device_attr *attr = &kd->kdattr; 310fcf5ef2aSThomas Huth int ret; 311fcf5ef2aSThomas Huth 312fcf5ef2aSThomas Huth /* If the device control API is available and we have a device fd on the 313fcf5ef2aSThomas Huth * KVMDevice struct, let's use the newer API 314fcf5ef2aSThomas Huth */ 315fcf5ef2aSThomas Huth if (kd->dev_fd >= 0) { 316fcf5ef2aSThomas Huth uint64_t addr = kd->kda.addr; 31719d1bd0bSEric Auger 31819d1bd0bSEric Auger addr |= kd->kda_addr_ormask; 319fcf5ef2aSThomas Huth attr->addr = (uintptr_t)&addr; 320fcf5ef2aSThomas Huth ret = kvm_device_ioctl(kd->dev_fd, KVM_SET_DEVICE_ATTR, attr); 321fcf5ef2aSThomas Huth } else { 322fcf5ef2aSThomas Huth ret = kvm_vm_ioctl(kvm_state, KVM_ARM_SET_DEVICE_ADDR, &kd->kda); 323fcf5ef2aSThomas Huth } 324fcf5ef2aSThomas Huth 325fcf5ef2aSThomas Huth if (ret < 0) { 326fcf5ef2aSThomas Huth fprintf(stderr, "Failed to set device address: %s\n", 327fcf5ef2aSThomas Huth strerror(-ret)); 328fcf5ef2aSThomas Huth abort(); 329fcf5ef2aSThomas Huth } 330fcf5ef2aSThomas Huth } 331fcf5ef2aSThomas Huth 332fcf5ef2aSThomas Huth static void kvm_arm_machine_init_done(Notifier *notifier, void *data) 333fcf5ef2aSThomas Huth { 334fcf5ef2aSThomas Huth KVMDevice *kd, *tkd; 335fcf5ef2aSThomas Huth 336fcf5ef2aSThomas Huth QSLIST_FOREACH_SAFE(kd, &kvm_devices_head, entries, tkd) { 337fcf5ef2aSThomas Huth if (kd->kda.addr != -1) { 338fcf5ef2aSThomas Huth kvm_arm_set_device_addr(kd); 339fcf5ef2aSThomas Huth } 340fcf5ef2aSThomas Huth memory_region_unref(kd->mr); 3415ff9aaabSZheng Xiang QSLIST_REMOVE_HEAD(&kvm_devices_head, entries); 342fcf5ef2aSThomas Huth g_free(kd); 343fcf5ef2aSThomas Huth } 3440bbe4354SPeter Xu memory_listener_unregister(&devlistener); 345fcf5ef2aSThomas Huth } 346fcf5ef2aSThomas Huth 347fcf5ef2aSThomas Huth static Notifier notify = { 348fcf5ef2aSThomas Huth .notify = kvm_arm_machine_init_done, 349fcf5ef2aSThomas Huth }; 350fcf5ef2aSThomas Huth 351fcf5ef2aSThomas Huth void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, 35219d1bd0bSEric Auger uint64_t attr, int dev_fd, uint64_t addr_ormask) 353fcf5ef2aSThomas Huth { 354fcf5ef2aSThomas Huth KVMDevice *kd; 355fcf5ef2aSThomas Huth 356fcf5ef2aSThomas Huth if (!kvm_irqchip_in_kernel()) { 357fcf5ef2aSThomas Huth return; 358fcf5ef2aSThomas Huth } 359fcf5ef2aSThomas Huth 360fcf5ef2aSThomas Huth if (QSLIST_EMPTY(&kvm_devices_head)) { 361fcf5ef2aSThomas Huth memory_listener_register(&devlistener, &address_space_memory); 362fcf5ef2aSThomas Huth qemu_add_machine_init_done_notifier(¬ify); 363fcf5ef2aSThomas Huth } 364fcf5ef2aSThomas Huth kd = g_new0(KVMDevice, 1); 365fcf5ef2aSThomas Huth kd->mr = mr; 366fcf5ef2aSThomas Huth kd->kda.id = devid; 367fcf5ef2aSThomas Huth kd->kda.addr = -1; 368fcf5ef2aSThomas Huth kd->kdattr.flags = 0; 369fcf5ef2aSThomas Huth kd->kdattr.group = group; 370fcf5ef2aSThomas Huth kd->kdattr.attr = attr; 371fcf5ef2aSThomas Huth kd->dev_fd = dev_fd; 37219d1bd0bSEric Auger kd->kda_addr_ormask = addr_ormask; 373fcf5ef2aSThomas Huth QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries); 374fcf5ef2aSThomas Huth memory_region_ref(kd->mr); 375fcf5ef2aSThomas Huth } 376fcf5ef2aSThomas Huth 377fcf5ef2aSThomas Huth static int compare_u64(const void *a, const void *b) 378fcf5ef2aSThomas Huth { 379fcf5ef2aSThomas Huth if (*(uint64_t *)a > *(uint64_t *)b) { 380fcf5ef2aSThomas Huth return 1; 381fcf5ef2aSThomas Huth } 382fcf5ef2aSThomas Huth if (*(uint64_t *)a < *(uint64_t *)b) { 383fcf5ef2aSThomas Huth return -1; 384fcf5ef2aSThomas Huth } 385fcf5ef2aSThomas Huth return 0; 386fcf5ef2aSThomas Huth } 387fcf5ef2aSThomas Huth 388e5ac4200SAndrew Jones /* 389e5ac4200SAndrew Jones * cpreg_values are sorted in ascending order by KVM register ID 390e5ac4200SAndrew Jones * (see kvm_arm_init_cpreg_list). This allows us to cheaply find 391e5ac4200SAndrew Jones * the storage for a KVM register by ID with a binary search. 392e5ac4200SAndrew Jones */ 393e5ac4200SAndrew Jones static uint64_t *kvm_arm_get_cpreg_ptr(ARMCPU *cpu, uint64_t regidx) 394e5ac4200SAndrew Jones { 395e5ac4200SAndrew Jones uint64_t *res; 396e5ac4200SAndrew Jones 397e5ac4200SAndrew Jones res = bsearch(®idx, cpu->cpreg_indexes, cpu->cpreg_array_len, 398e5ac4200SAndrew Jones sizeof(uint64_t), compare_u64); 399e5ac4200SAndrew Jones assert(res); 400e5ac4200SAndrew Jones 401e5ac4200SAndrew Jones return &cpu->cpreg_values[res - cpu->cpreg_indexes]; 402e5ac4200SAndrew Jones } 403e5ac4200SAndrew Jones 404c8a44709SDongjiu Geng /* Initialize the ARMCPU cpreg list according to the kernel's 405fcf5ef2aSThomas Huth * definition of what CPU registers it knows about (and throw away 406fcf5ef2aSThomas Huth * the previous TCG-created cpreg list). 407fcf5ef2aSThomas Huth */ 408fcf5ef2aSThomas Huth int kvm_arm_init_cpreg_list(ARMCPU *cpu) 409fcf5ef2aSThomas Huth { 410fcf5ef2aSThomas Huth struct kvm_reg_list rl; 411fcf5ef2aSThomas Huth struct kvm_reg_list *rlp; 412fcf5ef2aSThomas Huth int i, ret, arraylen; 413fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 414fcf5ef2aSThomas Huth 415fcf5ef2aSThomas Huth rl.n = 0; 416fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, &rl); 417fcf5ef2aSThomas Huth if (ret != -E2BIG) { 418fcf5ef2aSThomas Huth return ret; 419fcf5ef2aSThomas Huth } 420fcf5ef2aSThomas Huth rlp = g_malloc(sizeof(struct kvm_reg_list) + rl.n * sizeof(uint64_t)); 421fcf5ef2aSThomas Huth rlp->n = rl.n; 422fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, rlp); 423fcf5ef2aSThomas Huth if (ret) { 424fcf5ef2aSThomas Huth goto out; 425fcf5ef2aSThomas Huth } 426fcf5ef2aSThomas Huth /* Sort the list we get back from the kernel, since cpreg_tuples 427fcf5ef2aSThomas Huth * must be in strictly ascending order. 428fcf5ef2aSThomas Huth */ 429fcf5ef2aSThomas Huth qsort(&rlp->reg, rlp->n, sizeof(rlp->reg[0]), compare_u64); 430fcf5ef2aSThomas Huth 431fcf5ef2aSThomas Huth for (i = 0, arraylen = 0; i < rlp->n; i++) { 432fcf5ef2aSThomas Huth if (!kvm_arm_reg_syncs_via_cpreg_list(rlp->reg[i])) { 433fcf5ef2aSThomas Huth continue; 434fcf5ef2aSThomas Huth } 435fcf5ef2aSThomas Huth switch (rlp->reg[i] & KVM_REG_SIZE_MASK) { 436fcf5ef2aSThomas Huth case KVM_REG_SIZE_U32: 437fcf5ef2aSThomas Huth case KVM_REG_SIZE_U64: 438fcf5ef2aSThomas Huth break; 439fcf5ef2aSThomas Huth default: 440fcf5ef2aSThomas Huth fprintf(stderr, "Can't handle size of register in kernel list\n"); 441fcf5ef2aSThomas Huth ret = -EINVAL; 442fcf5ef2aSThomas Huth goto out; 443fcf5ef2aSThomas Huth } 444fcf5ef2aSThomas Huth 445fcf5ef2aSThomas Huth arraylen++; 446fcf5ef2aSThomas Huth } 447fcf5ef2aSThomas Huth 448fcf5ef2aSThomas Huth cpu->cpreg_indexes = g_renew(uint64_t, cpu->cpreg_indexes, arraylen); 449fcf5ef2aSThomas Huth cpu->cpreg_values = g_renew(uint64_t, cpu->cpreg_values, arraylen); 450fcf5ef2aSThomas Huth cpu->cpreg_vmstate_indexes = g_renew(uint64_t, cpu->cpreg_vmstate_indexes, 451fcf5ef2aSThomas Huth arraylen); 452fcf5ef2aSThomas Huth cpu->cpreg_vmstate_values = g_renew(uint64_t, cpu->cpreg_vmstate_values, 453fcf5ef2aSThomas Huth arraylen); 454fcf5ef2aSThomas Huth cpu->cpreg_array_len = arraylen; 455fcf5ef2aSThomas Huth cpu->cpreg_vmstate_array_len = arraylen; 456fcf5ef2aSThomas Huth 457fcf5ef2aSThomas Huth for (i = 0, arraylen = 0; i < rlp->n; i++) { 458fcf5ef2aSThomas Huth uint64_t regidx = rlp->reg[i]; 459fcf5ef2aSThomas Huth if (!kvm_arm_reg_syncs_via_cpreg_list(regidx)) { 460fcf5ef2aSThomas Huth continue; 461fcf5ef2aSThomas Huth } 462fcf5ef2aSThomas Huth cpu->cpreg_indexes[arraylen] = regidx; 463fcf5ef2aSThomas Huth arraylen++; 464fcf5ef2aSThomas Huth } 465fcf5ef2aSThomas Huth assert(cpu->cpreg_array_len == arraylen); 466fcf5ef2aSThomas Huth 467fcf5ef2aSThomas Huth if (!write_kvmstate_to_list(cpu)) { 468fcf5ef2aSThomas Huth /* Shouldn't happen unless kernel is inconsistent about 469fcf5ef2aSThomas Huth * what registers exist. 470fcf5ef2aSThomas Huth */ 471fcf5ef2aSThomas Huth fprintf(stderr, "Initial read of kernel register state failed\n"); 472fcf5ef2aSThomas Huth ret = -EINVAL; 473fcf5ef2aSThomas Huth goto out; 474fcf5ef2aSThomas Huth } 475fcf5ef2aSThomas Huth 476fcf5ef2aSThomas Huth out: 477fcf5ef2aSThomas Huth g_free(rlp); 478fcf5ef2aSThomas Huth return ret; 479fcf5ef2aSThomas Huth } 480fcf5ef2aSThomas Huth 481fcf5ef2aSThomas Huth bool write_kvmstate_to_list(ARMCPU *cpu) 482fcf5ef2aSThomas Huth { 483fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 484fcf5ef2aSThomas Huth int i; 485fcf5ef2aSThomas Huth bool ok = true; 486fcf5ef2aSThomas Huth 487fcf5ef2aSThomas Huth for (i = 0; i < cpu->cpreg_array_len; i++) { 488fcf5ef2aSThomas Huth struct kvm_one_reg r; 489fcf5ef2aSThomas Huth uint64_t regidx = cpu->cpreg_indexes[i]; 490fcf5ef2aSThomas Huth uint32_t v32; 491fcf5ef2aSThomas Huth int ret; 492fcf5ef2aSThomas Huth 493fcf5ef2aSThomas Huth r.id = regidx; 494fcf5ef2aSThomas Huth 495fcf5ef2aSThomas Huth switch (regidx & KVM_REG_SIZE_MASK) { 496fcf5ef2aSThomas Huth case KVM_REG_SIZE_U32: 497fcf5ef2aSThomas Huth r.addr = (uintptr_t)&v32; 498fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r); 499fcf5ef2aSThomas Huth if (!ret) { 500fcf5ef2aSThomas Huth cpu->cpreg_values[i] = v32; 501fcf5ef2aSThomas Huth } 502fcf5ef2aSThomas Huth break; 503fcf5ef2aSThomas Huth case KVM_REG_SIZE_U64: 504fcf5ef2aSThomas Huth r.addr = (uintptr_t)(cpu->cpreg_values + i); 505fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r); 506fcf5ef2aSThomas Huth break; 507fcf5ef2aSThomas Huth default: 508fcf5ef2aSThomas Huth abort(); 509fcf5ef2aSThomas Huth } 510fcf5ef2aSThomas Huth if (ret) { 511fcf5ef2aSThomas Huth ok = false; 512fcf5ef2aSThomas Huth } 513fcf5ef2aSThomas Huth } 514fcf5ef2aSThomas Huth return ok; 515fcf5ef2aSThomas Huth } 516fcf5ef2aSThomas Huth 517fcf5ef2aSThomas Huth bool write_list_to_kvmstate(ARMCPU *cpu, int level) 518fcf5ef2aSThomas Huth { 519fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 520fcf5ef2aSThomas Huth int i; 521fcf5ef2aSThomas Huth bool ok = true; 522fcf5ef2aSThomas Huth 523fcf5ef2aSThomas Huth for (i = 0; i < cpu->cpreg_array_len; i++) { 524fcf5ef2aSThomas Huth struct kvm_one_reg r; 525fcf5ef2aSThomas Huth uint64_t regidx = cpu->cpreg_indexes[i]; 526fcf5ef2aSThomas Huth uint32_t v32; 527fcf5ef2aSThomas Huth int ret; 528fcf5ef2aSThomas Huth 529fcf5ef2aSThomas Huth if (kvm_arm_cpreg_level(regidx) > level) { 530fcf5ef2aSThomas Huth continue; 531fcf5ef2aSThomas Huth } 532fcf5ef2aSThomas Huth 533fcf5ef2aSThomas Huth r.id = regidx; 534fcf5ef2aSThomas Huth switch (regidx & KVM_REG_SIZE_MASK) { 535fcf5ef2aSThomas Huth case KVM_REG_SIZE_U32: 536fcf5ef2aSThomas Huth v32 = cpu->cpreg_values[i]; 537fcf5ef2aSThomas Huth r.addr = (uintptr_t)&v32; 538fcf5ef2aSThomas Huth break; 539fcf5ef2aSThomas Huth case KVM_REG_SIZE_U64: 540fcf5ef2aSThomas Huth r.addr = (uintptr_t)(cpu->cpreg_values + i); 541fcf5ef2aSThomas Huth break; 542fcf5ef2aSThomas Huth default: 543fcf5ef2aSThomas Huth abort(); 544fcf5ef2aSThomas Huth } 545fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r); 546fcf5ef2aSThomas Huth if (ret) { 547fcf5ef2aSThomas Huth /* We might fail for "unknown register" and also for 548fcf5ef2aSThomas Huth * "you tried to set a register which is constant with 549fcf5ef2aSThomas Huth * a different value from what it actually contains". 550fcf5ef2aSThomas Huth */ 551fcf5ef2aSThomas Huth ok = false; 552fcf5ef2aSThomas Huth } 553fcf5ef2aSThomas Huth } 554fcf5ef2aSThomas Huth return ok; 555fcf5ef2aSThomas Huth } 556fcf5ef2aSThomas Huth 557e5ac4200SAndrew Jones void kvm_arm_cpu_pre_save(ARMCPU *cpu) 558e5ac4200SAndrew Jones { 559e5ac4200SAndrew Jones /* KVM virtual time adjustment */ 560e5ac4200SAndrew Jones if (cpu->kvm_vtime_dirty) { 561e5ac4200SAndrew Jones *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT) = cpu->kvm_vtime; 562e5ac4200SAndrew Jones } 563e5ac4200SAndrew Jones } 564e5ac4200SAndrew Jones 565e5ac4200SAndrew Jones void kvm_arm_cpu_post_load(ARMCPU *cpu) 566e5ac4200SAndrew Jones { 567e5ac4200SAndrew Jones /* KVM virtual time adjustment */ 568e5ac4200SAndrew Jones if (cpu->kvm_adjvtime) { 569e5ac4200SAndrew Jones cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT); 570e5ac4200SAndrew Jones cpu->kvm_vtime_dirty = true; 571e5ac4200SAndrew Jones } 572e5ac4200SAndrew Jones } 573e5ac4200SAndrew Jones 574fcf5ef2aSThomas Huth void kvm_arm_reset_vcpu(ARMCPU *cpu) 575fcf5ef2aSThomas Huth { 576fcf5ef2aSThomas Huth int ret; 577fcf5ef2aSThomas Huth 578fcf5ef2aSThomas Huth /* Re-init VCPU so that all registers are set to 579fcf5ef2aSThomas Huth * their respective reset values. 580fcf5ef2aSThomas Huth */ 581fcf5ef2aSThomas Huth ret = kvm_arm_vcpu_init(CPU(cpu)); 582fcf5ef2aSThomas Huth if (ret < 0) { 583fcf5ef2aSThomas Huth fprintf(stderr, "kvm_arm_vcpu_init failed: %s\n", strerror(-ret)); 584fcf5ef2aSThomas Huth abort(); 585fcf5ef2aSThomas Huth } 586fcf5ef2aSThomas Huth if (!write_kvmstate_to_list(cpu)) { 587fcf5ef2aSThomas Huth fprintf(stderr, "write_kvmstate_to_list failed\n"); 588fcf5ef2aSThomas Huth abort(); 589fcf5ef2aSThomas Huth } 590b698e4eeSPeter Maydell /* 591b698e4eeSPeter Maydell * Sync the reset values also into the CPUState. This is necessary 592b698e4eeSPeter Maydell * because the next thing we do will be a kvm_arch_put_registers() 593b698e4eeSPeter Maydell * which will update the list values from the CPUState before copying 594b698e4eeSPeter Maydell * the list values back to KVM. It's OK to ignore failure returns here 595b698e4eeSPeter Maydell * for the same reason we do so in kvm_arch_get_registers(). 596b698e4eeSPeter Maydell */ 597b698e4eeSPeter Maydell write_list_to_cpustate(cpu); 598fcf5ef2aSThomas Huth } 599fcf5ef2aSThomas Huth 600fcf5ef2aSThomas Huth /* 601fcf5ef2aSThomas Huth * Update KVM's MP_STATE based on what QEMU thinks it is 602fcf5ef2aSThomas Huth */ 603fcf5ef2aSThomas Huth int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu) 604fcf5ef2aSThomas Huth { 605fcf5ef2aSThomas Huth if (cap_has_mp_state) { 606fcf5ef2aSThomas Huth struct kvm_mp_state mp_state = { 607062ba099SAlex Bennée .mp_state = (cpu->power_state == PSCI_OFF) ? 608062ba099SAlex Bennée KVM_MP_STATE_STOPPED : KVM_MP_STATE_RUNNABLE 609fcf5ef2aSThomas Huth }; 610fcf5ef2aSThomas Huth int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state); 611fcf5ef2aSThomas Huth if (ret) { 612fcf5ef2aSThomas Huth fprintf(stderr, "%s: failed to set MP_STATE %d/%s\n", 613fcf5ef2aSThomas Huth __func__, ret, strerror(-ret)); 614fcf5ef2aSThomas Huth return -1; 615fcf5ef2aSThomas Huth } 616fcf5ef2aSThomas Huth } 617fcf5ef2aSThomas Huth 618fcf5ef2aSThomas Huth return 0; 619fcf5ef2aSThomas Huth } 620fcf5ef2aSThomas Huth 621fcf5ef2aSThomas Huth /* 622fcf5ef2aSThomas Huth * Sync the KVM MP_STATE into QEMU 623fcf5ef2aSThomas Huth */ 624fcf5ef2aSThomas Huth int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu) 625fcf5ef2aSThomas Huth { 626fcf5ef2aSThomas Huth if (cap_has_mp_state) { 627fcf5ef2aSThomas Huth struct kvm_mp_state mp_state; 628fcf5ef2aSThomas Huth int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MP_STATE, &mp_state); 629fcf5ef2aSThomas Huth if (ret) { 630fcf5ef2aSThomas Huth fprintf(stderr, "%s: failed to get MP_STATE %d/%s\n", 631fcf5ef2aSThomas Huth __func__, ret, strerror(-ret)); 632fcf5ef2aSThomas Huth abort(); 633fcf5ef2aSThomas Huth } 634062ba099SAlex Bennée cpu->power_state = (mp_state.mp_state == KVM_MP_STATE_STOPPED) ? 635062ba099SAlex Bennée PSCI_OFF : PSCI_ON; 636fcf5ef2aSThomas Huth } 637fcf5ef2aSThomas Huth 638fcf5ef2aSThomas Huth return 0; 639fcf5ef2aSThomas Huth } 640fcf5ef2aSThomas Huth 641e5ac4200SAndrew Jones void kvm_arm_get_virtual_time(CPUState *cs) 642e5ac4200SAndrew Jones { 643e5ac4200SAndrew Jones ARMCPU *cpu = ARM_CPU(cs); 644e5ac4200SAndrew Jones struct kvm_one_reg reg = { 645e5ac4200SAndrew Jones .id = KVM_REG_ARM_TIMER_CNT, 646e5ac4200SAndrew Jones .addr = (uintptr_t)&cpu->kvm_vtime, 647e5ac4200SAndrew Jones }; 648e5ac4200SAndrew Jones int ret; 649e5ac4200SAndrew Jones 650e5ac4200SAndrew Jones if (cpu->kvm_vtime_dirty) { 651e5ac4200SAndrew Jones return; 652e5ac4200SAndrew Jones } 653e5ac4200SAndrew Jones 654e5ac4200SAndrew Jones ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 655e5ac4200SAndrew Jones if (ret) { 656e5ac4200SAndrew Jones error_report("Failed to get KVM_REG_ARM_TIMER_CNT"); 657e5ac4200SAndrew Jones abort(); 658e5ac4200SAndrew Jones } 659e5ac4200SAndrew Jones 660e5ac4200SAndrew Jones cpu->kvm_vtime_dirty = true; 661e5ac4200SAndrew Jones } 662e5ac4200SAndrew Jones 663e5ac4200SAndrew Jones void kvm_arm_put_virtual_time(CPUState *cs) 664e5ac4200SAndrew Jones { 665e5ac4200SAndrew Jones ARMCPU *cpu = ARM_CPU(cs); 666e5ac4200SAndrew Jones struct kvm_one_reg reg = { 667e5ac4200SAndrew Jones .id = KVM_REG_ARM_TIMER_CNT, 668e5ac4200SAndrew Jones .addr = (uintptr_t)&cpu->kvm_vtime, 669e5ac4200SAndrew Jones }; 670e5ac4200SAndrew Jones int ret; 671e5ac4200SAndrew Jones 672e5ac4200SAndrew Jones if (!cpu->kvm_vtime_dirty) { 673e5ac4200SAndrew Jones return; 674e5ac4200SAndrew Jones } 675e5ac4200SAndrew Jones 676e5ac4200SAndrew Jones ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 677e5ac4200SAndrew Jones if (ret) { 678e5ac4200SAndrew Jones error_report("Failed to set KVM_REG_ARM_TIMER_CNT"); 679e5ac4200SAndrew Jones abort(); 680e5ac4200SAndrew Jones } 681e5ac4200SAndrew Jones 682e5ac4200SAndrew Jones cpu->kvm_vtime_dirty = false; 683e5ac4200SAndrew Jones } 684e5ac4200SAndrew Jones 685202ccb6bSDongjiu Geng int kvm_put_vcpu_events(ARMCPU *cpu) 686202ccb6bSDongjiu Geng { 687202ccb6bSDongjiu Geng CPUARMState *env = &cpu->env; 688202ccb6bSDongjiu Geng struct kvm_vcpu_events events; 689202ccb6bSDongjiu Geng int ret; 690202ccb6bSDongjiu Geng 691202ccb6bSDongjiu Geng if (!kvm_has_vcpu_events()) { 692202ccb6bSDongjiu Geng return 0; 693202ccb6bSDongjiu Geng } 694202ccb6bSDongjiu Geng 695202ccb6bSDongjiu Geng memset(&events, 0, sizeof(events)); 696202ccb6bSDongjiu Geng events.exception.serror_pending = env->serror.pending; 697202ccb6bSDongjiu Geng 698202ccb6bSDongjiu Geng /* Inject SError to guest with specified syndrome if host kernel 699202ccb6bSDongjiu Geng * supports it, otherwise inject SError without syndrome. 700202ccb6bSDongjiu Geng */ 701202ccb6bSDongjiu Geng if (cap_has_inject_serror_esr) { 702202ccb6bSDongjiu Geng events.exception.serror_has_esr = env->serror.has_esr; 703202ccb6bSDongjiu Geng events.exception.serror_esr = env->serror.esr; 704202ccb6bSDongjiu Geng } 705202ccb6bSDongjiu Geng 706202ccb6bSDongjiu Geng ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_VCPU_EVENTS, &events); 707202ccb6bSDongjiu Geng if (ret) { 708202ccb6bSDongjiu Geng error_report("failed to put vcpu events"); 709202ccb6bSDongjiu Geng } 710202ccb6bSDongjiu Geng 711202ccb6bSDongjiu Geng return ret; 712202ccb6bSDongjiu Geng } 713202ccb6bSDongjiu Geng 714202ccb6bSDongjiu Geng int kvm_get_vcpu_events(ARMCPU *cpu) 715202ccb6bSDongjiu Geng { 716202ccb6bSDongjiu Geng CPUARMState *env = &cpu->env; 717202ccb6bSDongjiu Geng struct kvm_vcpu_events events; 718202ccb6bSDongjiu Geng int ret; 719202ccb6bSDongjiu Geng 720202ccb6bSDongjiu Geng if (!kvm_has_vcpu_events()) { 721202ccb6bSDongjiu Geng return 0; 722202ccb6bSDongjiu Geng } 723202ccb6bSDongjiu Geng 724202ccb6bSDongjiu Geng memset(&events, 0, sizeof(events)); 725202ccb6bSDongjiu Geng ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_VCPU_EVENTS, &events); 726202ccb6bSDongjiu Geng if (ret) { 727202ccb6bSDongjiu Geng error_report("failed to get vcpu events"); 728202ccb6bSDongjiu Geng return ret; 729202ccb6bSDongjiu Geng } 730202ccb6bSDongjiu Geng 731202ccb6bSDongjiu Geng env->serror.pending = events.exception.serror_pending; 732202ccb6bSDongjiu Geng env->serror.has_esr = events.exception.serror_has_esr; 733202ccb6bSDongjiu Geng env->serror.esr = events.exception.serror_esr; 734202ccb6bSDongjiu Geng 735202ccb6bSDongjiu Geng return 0; 736202ccb6bSDongjiu Geng } 737202ccb6bSDongjiu Geng 738fcf5ef2aSThomas Huth void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 739fcf5ef2aSThomas Huth { 740fcf5ef2aSThomas Huth } 741fcf5ef2aSThomas Huth 742fcf5ef2aSThomas Huth MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 743fcf5ef2aSThomas Huth { 7445d721b78SAlexander Graf ARMCPU *cpu; 7455d721b78SAlexander Graf uint32_t switched_level; 7465d721b78SAlexander Graf 7475d721b78SAlexander Graf if (kvm_irqchip_in_kernel()) { 7485d721b78SAlexander Graf /* 7495d721b78SAlexander Graf * We only need to sync timer states with user-space interrupt 7505d721b78SAlexander Graf * controllers, so return early and save cycles if we don't. 7515d721b78SAlexander Graf */ 7525d721b78SAlexander Graf return MEMTXATTRS_UNSPECIFIED; 7535d721b78SAlexander Graf } 7545d721b78SAlexander Graf 7555d721b78SAlexander Graf cpu = ARM_CPU(cs); 7565d721b78SAlexander Graf 7575d721b78SAlexander Graf /* Synchronize our shadowed in-kernel device irq lines with the kvm ones */ 7585d721b78SAlexander Graf if (run->s.regs.device_irq_level != cpu->device_irq_level) { 7595d721b78SAlexander Graf switched_level = cpu->device_irq_level ^ run->s.regs.device_irq_level; 7605d721b78SAlexander Graf 7615d721b78SAlexander Graf qemu_mutex_lock_iothread(); 7625d721b78SAlexander Graf 7635d721b78SAlexander Graf if (switched_level & KVM_ARM_DEV_EL1_VTIMER) { 7645d721b78SAlexander Graf qemu_set_irq(cpu->gt_timer_outputs[GTIMER_VIRT], 7655d721b78SAlexander Graf !!(run->s.regs.device_irq_level & 7665d721b78SAlexander Graf KVM_ARM_DEV_EL1_VTIMER)); 7675d721b78SAlexander Graf switched_level &= ~KVM_ARM_DEV_EL1_VTIMER; 7685d721b78SAlexander Graf } 7695d721b78SAlexander Graf 7705d721b78SAlexander Graf if (switched_level & KVM_ARM_DEV_EL1_PTIMER) { 7715d721b78SAlexander Graf qemu_set_irq(cpu->gt_timer_outputs[GTIMER_PHYS], 7725d721b78SAlexander Graf !!(run->s.regs.device_irq_level & 7735d721b78SAlexander Graf KVM_ARM_DEV_EL1_PTIMER)); 7745d721b78SAlexander Graf switched_level &= ~KVM_ARM_DEV_EL1_PTIMER; 7755d721b78SAlexander Graf } 7765d721b78SAlexander Graf 777b1659527SAndrew Jones if (switched_level & KVM_ARM_DEV_PMU) { 778b1659527SAndrew Jones qemu_set_irq(cpu->pmu_interrupt, 779b1659527SAndrew Jones !!(run->s.regs.device_irq_level & KVM_ARM_DEV_PMU)); 780b1659527SAndrew Jones switched_level &= ~KVM_ARM_DEV_PMU; 781b1659527SAndrew Jones } 7825d721b78SAlexander Graf 7835d721b78SAlexander Graf if (switched_level) { 7845d721b78SAlexander Graf qemu_log_mask(LOG_UNIMP, "%s: unhandled in-kernel device IRQ %x\n", 7855d721b78SAlexander Graf __func__, switched_level); 7865d721b78SAlexander Graf } 7875d721b78SAlexander Graf 7885d721b78SAlexander Graf /* We also mark unknown levels as processed to not waste cycles */ 7895d721b78SAlexander Graf cpu->device_irq_level = run->s.regs.device_irq_level; 7905d721b78SAlexander Graf qemu_mutex_unlock_iothread(); 7915d721b78SAlexander Graf } 7925d721b78SAlexander Graf 793fcf5ef2aSThomas Huth return MEMTXATTRS_UNSPECIFIED; 794fcf5ef2aSThomas Huth } 795fcf5ef2aSThomas Huth 796e5ac4200SAndrew Jones void kvm_arm_vm_state_change(void *opaque, int running, RunState state) 797e5ac4200SAndrew Jones { 798e5ac4200SAndrew Jones CPUState *cs = opaque; 799e5ac4200SAndrew Jones ARMCPU *cpu = ARM_CPU(cs); 800e5ac4200SAndrew Jones 801e5ac4200SAndrew Jones if (running) { 802e5ac4200SAndrew Jones if (cpu->kvm_adjvtime) { 803e5ac4200SAndrew Jones kvm_arm_put_virtual_time(cs); 804e5ac4200SAndrew Jones } 805e5ac4200SAndrew Jones } else { 806e5ac4200SAndrew Jones if (cpu->kvm_adjvtime) { 807e5ac4200SAndrew Jones kvm_arm_get_virtual_time(cs); 808e5ac4200SAndrew Jones } 809e5ac4200SAndrew Jones } 810e5ac4200SAndrew Jones } 811fcf5ef2aSThomas Huth 812fcf5ef2aSThomas Huth int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 813fcf5ef2aSThomas Huth { 814fcf5ef2aSThomas Huth int ret = 0; 815fcf5ef2aSThomas Huth 816fcf5ef2aSThomas Huth switch (run->exit_reason) { 817fcf5ef2aSThomas Huth case KVM_EXIT_DEBUG: 818fcf5ef2aSThomas Huth if (kvm_arm_handle_debug(cs, &run->debug.arch)) { 819fcf5ef2aSThomas Huth ret = EXCP_DEBUG; 820fcf5ef2aSThomas Huth } /* otherwise return to guest */ 821fcf5ef2aSThomas Huth break; 822fcf5ef2aSThomas Huth default: 823fcf5ef2aSThomas Huth qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", 824fcf5ef2aSThomas Huth __func__, run->exit_reason); 825fcf5ef2aSThomas Huth break; 826fcf5ef2aSThomas Huth } 827fcf5ef2aSThomas Huth return ret; 828fcf5ef2aSThomas Huth } 829fcf5ef2aSThomas Huth 830fcf5ef2aSThomas Huth bool kvm_arch_stop_on_emulation_error(CPUState *cs) 831fcf5ef2aSThomas Huth { 832fcf5ef2aSThomas Huth return true; 833fcf5ef2aSThomas Huth } 834fcf5ef2aSThomas Huth 835fcf5ef2aSThomas Huth int kvm_arch_process_async_events(CPUState *cs) 836fcf5ef2aSThomas Huth { 837fcf5ef2aSThomas Huth return 0; 838fcf5ef2aSThomas Huth } 839fcf5ef2aSThomas Huth 840fcf5ef2aSThomas Huth /* The #ifdef protections are until 32bit headers are imported and can 841fcf5ef2aSThomas Huth * be removed once both 32 and 64 bit reach feature parity. 842fcf5ef2aSThomas Huth */ 843fcf5ef2aSThomas Huth void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) 844fcf5ef2aSThomas Huth { 845fcf5ef2aSThomas Huth #ifdef KVM_GUESTDBG_USE_SW_BP 846fcf5ef2aSThomas Huth if (kvm_sw_breakpoints_active(cs)) { 847fcf5ef2aSThomas Huth dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; 848fcf5ef2aSThomas Huth } 849fcf5ef2aSThomas Huth #endif 850fcf5ef2aSThomas Huth #ifdef KVM_GUESTDBG_USE_HW 851fcf5ef2aSThomas Huth if (kvm_arm_hw_debug_active(cs)) { 852fcf5ef2aSThomas Huth dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW; 853fcf5ef2aSThomas Huth kvm_arm_copy_hw_debug_data(&dbg->arch); 854fcf5ef2aSThomas Huth } 855fcf5ef2aSThomas Huth #endif 856fcf5ef2aSThomas Huth } 857fcf5ef2aSThomas Huth 858fcf5ef2aSThomas Huth void kvm_arch_init_irq_routing(KVMState *s) 859fcf5ef2aSThomas Huth { 860fcf5ef2aSThomas Huth } 861fcf5ef2aSThomas Huth 8624376c40dSPaolo Bonzini int kvm_arch_irqchip_create(KVMState *s) 863fcf5ef2aSThomas Huth { 8644376c40dSPaolo Bonzini if (kvm_kernel_irqchip_split()) { 865fcf5ef2aSThomas Huth perror("-machine kernel_irqchip=split is not supported on ARM."); 866fcf5ef2aSThomas Huth exit(1); 867fcf5ef2aSThomas Huth } 868fcf5ef2aSThomas Huth 869fcf5ef2aSThomas Huth /* If we can create the VGIC using the newer device control API, we 870fcf5ef2aSThomas Huth * let the device do this when it initializes itself, otherwise we 871fcf5ef2aSThomas Huth * fall back to the old API */ 872fcf5ef2aSThomas Huth return kvm_check_extension(s, KVM_CAP_DEVICE_CTRL); 873fcf5ef2aSThomas Huth } 874fcf5ef2aSThomas Huth 875fcf5ef2aSThomas Huth int kvm_arm_vgic_probe(void) 876fcf5ef2aSThomas Huth { 877d45efe47SEric Auger int val = 0; 878d45efe47SEric Auger 879fcf5ef2aSThomas Huth if (kvm_create_device(kvm_state, 880fcf5ef2aSThomas Huth KVM_DEV_TYPE_ARM_VGIC_V3, true) == 0) { 881d45efe47SEric Auger val |= KVM_ARM_VGIC_V3; 882fcf5ef2aSThomas Huth } 883d45efe47SEric Auger if (kvm_create_device(kvm_state, 884d45efe47SEric Auger KVM_DEV_TYPE_ARM_VGIC_V2, true) == 0) { 885d45efe47SEric Auger val |= KVM_ARM_VGIC_V2; 886d45efe47SEric Auger } 887d45efe47SEric Auger return val; 888fcf5ef2aSThomas Huth } 889fcf5ef2aSThomas Huth 890f6530926SEric Auger int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level) 891f6530926SEric Auger { 892f6530926SEric Auger int kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT) | irq; 893f6530926SEric Auger int cpu_idx1 = cpu % 256; 894f6530926SEric Auger int cpu_idx2 = cpu / 256; 895f6530926SEric Auger 896f6530926SEric Auger kvm_irq |= (cpu_idx1 << KVM_ARM_IRQ_VCPU_SHIFT) | 897f6530926SEric Auger (cpu_idx2 << KVM_ARM_IRQ_VCPU2_SHIFT); 898f6530926SEric Auger 899f6530926SEric Auger return kvm_set_irq(kvm_state, kvm_irq, !!level); 900f6530926SEric Auger } 901f6530926SEric Auger 902fcf5ef2aSThomas Huth int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 903fcf5ef2aSThomas Huth uint64_t address, uint32_t data, PCIDevice *dev) 904fcf5ef2aSThomas Huth { 905b05c81d2SEric Auger AddressSpace *as = pci_device_iommu_address_space(dev); 906b05c81d2SEric Auger hwaddr xlat, len, doorbell_gpa; 907b05c81d2SEric Auger MemoryRegionSection mrs; 908b05c81d2SEric Auger MemoryRegion *mr; 909b05c81d2SEric Auger int ret = 1; 910b05c81d2SEric Auger 911b05c81d2SEric Auger if (as == &address_space_memory) { 912fcf5ef2aSThomas Huth return 0; 913fcf5ef2aSThomas Huth } 914fcf5ef2aSThomas Huth 915b05c81d2SEric Auger /* MSI doorbell address is translated by an IOMMU */ 916b05c81d2SEric Auger 917b05c81d2SEric Auger rcu_read_lock(); 918bc6b1cecSPeter Maydell mr = address_space_translate(as, address, &xlat, &len, true, 919bc6b1cecSPeter Maydell MEMTXATTRS_UNSPECIFIED); 920b05c81d2SEric Auger if (!mr) { 921b05c81d2SEric Auger goto unlock; 922b05c81d2SEric Auger } 923b05c81d2SEric Auger mrs = memory_region_find(mr, xlat, 1); 924b05c81d2SEric Auger if (!mrs.mr) { 925b05c81d2SEric Auger goto unlock; 926b05c81d2SEric Auger } 927b05c81d2SEric Auger 928b05c81d2SEric Auger doorbell_gpa = mrs.offset_within_address_space; 929b05c81d2SEric Auger memory_region_unref(mrs.mr); 930b05c81d2SEric Auger 931b05c81d2SEric Auger route->u.msi.address_lo = doorbell_gpa; 932b05c81d2SEric Auger route->u.msi.address_hi = doorbell_gpa >> 32; 933b05c81d2SEric Auger 934b05c81d2SEric Auger trace_kvm_arm_fixup_msi_route(address, doorbell_gpa); 935b05c81d2SEric Auger 936b05c81d2SEric Auger ret = 0; 937b05c81d2SEric Auger 938b05c81d2SEric Auger unlock: 939b05c81d2SEric Auger rcu_read_unlock(); 940b05c81d2SEric Auger return ret; 941b05c81d2SEric Auger } 942b05c81d2SEric Auger 943fcf5ef2aSThomas Huth int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 944fcf5ef2aSThomas Huth int vector, PCIDevice *dev) 945fcf5ef2aSThomas Huth { 946fcf5ef2aSThomas Huth return 0; 947fcf5ef2aSThomas Huth } 948fcf5ef2aSThomas Huth 949fcf5ef2aSThomas Huth int kvm_arch_release_virq_post(int virq) 950fcf5ef2aSThomas Huth { 951fcf5ef2aSThomas Huth return 0; 952fcf5ef2aSThomas Huth } 953fcf5ef2aSThomas Huth 954fcf5ef2aSThomas Huth int kvm_arch_msi_data_to_gsi(uint32_t data) 955fcf5ef2aSThomas Huth { 956fcf5ef2aSThomas Huth return (data - 32) & 0xffff; 957fcf5ef2aSThomas Huth } 958