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 { 1979e6f8d8aSfangying ARMCPU *cpu = ARM_CPU(obj); 1989e6f8d8aSfangying CPUARMState *env = &cpu->env; 199dea101a1SAndrew Jones 2009e6f8d8aSfangying if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) { 2019e6f8d8aSfangying cpu->kvm_adjvtime = true; 202dea101a1SAndrew Jones object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get, 203d2623129SMarkus 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 } 2099e6f8d8aSfangying } 210dea101a1SAndrew Jones 211*7d20e681SPhilippe Mathieu-Daudé bool kvm_arm_pmu_supported(void) 212ae502508SAndrew Jones { 213*7d20e681SPhilippe Mathieu-Daudé return kvm_check_extension(kvm_state, KVM_CAP_ARM_PMU_V3); 214ae502508SAndrew Jones } 215ae502508SAndrew Jones 216a27382e2SEric Auger int kvm_arm_get_max_vm_ipa_size(MachineState *ms) 217a27382e2SEric Auger { 218a27382e2SEric Auger KVMState *s = KVM_STATE(ms->accelerator); 219a27382e2SEric Auger int ret; 220a27382e2SEric Auger 221a27382e2SEric Auger ret = kvm_check_extension(s, KVM_CAP_ARM_VM_IPA_SIZE); 222a27382e2SEric Auger return ret > 0 ? ret : 40; 223a27382e2SEric Auger } 224a27382e2SEric Auger 225fcf5ef2aSThomas Huth int kvm_arch_init(MachineState *ms, KVMState *s) 226fcf5ef2aSThomas Huth { 227fff9f555SEric Auger int ret = 0; 228fcf5ef2aSThomas Huth /* For ARM interrupt delivery is always asynchronous, 229fcf5ef2aSThomas Huth * whether we are using an in-kernel VGIC or not. 230fcf5ef2aSThomas Huth */ 231fcf5ef2aSThomas Huth kvm_async_interrupts_allowed = true; 232fcf5ef2aSThomas Huth 2335d721b78SAlexander Graf /* 2345d721b78SAlexander Graf * PSCI wakes up secondary cores, so we always need to 2355d721b78SAlexander Graf * have vCPUs waiting in kernel space 2365d721b78SAlexander Graf */ 2375d721b78SAlexander Graf kvm_halt_in_kernel_allowed = true; 2385d721b78SAlexander Graf 239fcf5ef2aSThomas Huth cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); 240fcf5ef2aSThomas Huth 241fff9f555SEric Auger if (ms->smp.cpus > 256 && 242fff9f555SEric Auger !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) { 243fff9f555SEric Auger error_report("Using more than 256 vcpus requires a host kernel " 244fff9f555SEric Auger "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2"); 245fff9f555SEric Auger ret = -EINVAL; 246fff9f555SEric Auger } 247fff9f555SEric Auger 248fff9f555SEric Auger return ret; 249fcf5ef2aSThomas Huth } 250fcf5ef2aSThomas Huth 251fcf5ef2aSThomas Huth unsigned long kvm_arch_vcpu_id(CPUState *cpu) 252fcf5ef2aSThomas Huth { 253fcf5ef2aSThomas Huth return cpu->cpu_index; 254fcf5ef2aSThomas Huth } 255fcf5ef2aSThomas Huth 256fcf5ef2aSThomas Huth /* We track all the KVM devices which need their memory addresses 257fcf5ef2aSThomas Huth * passing to the kernel in a list of these structures. 258fcf5ef2aSThomas Huth * When board init is complete we run through the list and 259fcf5ef2aSThomas Huth * tell the kernel the base addresses of the memory regions. 260fcf5ef2aSThomas Huth * We use a MemoryListener to track mapping and unmapping of 261fcf5ef2aSThomas Huth * the regions during board creation, so the board models don't 262fcf5ef2aSThomas Huth * need to do anything special for the KVM case. 26319d1bd0bSEric Auger * 26419d1bd0bSEric Auger * Sometimes the address must be OR'ed with some other fields 26519d1bd0bSEric Auger * (for example for KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION). 26619d1bd0bSEric Auger * @kda_addr_ormask aims at storing the value of those fields. 267fcf5ef2aSThomas Huth */ 268fcf5ef2aSThomas Huth typedef struct KVMDevice { 269fcf5ef2aSThomas Huth struct kvm_arm_device_addr kda; 270fcf5ef2aSThomas Huth struct kvm_device_attr kdattr; 27119d1bd0bSEric Auger uint64_t kda_addr_ormask; 272fcf5ef2aSThomas Huth MemoryRegion *mr; 273fcf5ef2aSThomas Huth QSLIST_ENTRY(KVMDevice) entries; 274fcf5ef2aSThomas Huth int dev_fd; 275fcf5ef2aSThomas Huth } KVMDevice; 276fcf5ef2aSThomas Huth 277b58deb34SPaolo Bonzini static QSLIST_HEAD(, KVMDevice) kvm_devices_head; 278fcf5ef2aSThomas Huth 279fcf5ef2aSThomas Huth static void kvm_arm_devlistener_add(MemoryListener *listener, 280fcf5ef2aSThomas Huth MemoryRegionSection *section) 281fcf5ef2aSThomas Huth { 282fcf5ef2aSThomas Huth KVMDevice *kd; 283fcf5ef2aSThomas Huth 284fcf5ef2aSThomas Huth QSLIST_FOREACH(kd, &kvm_devices_head, entries) { 285fcf5ef2aSThomas Huth if (section->mr == kd->mr) { 286fcf5ef2aSThomas Huth kd->kda.addr = section->offset_within_address_space; 287fcf5ef2aSThomas Huth } 288fcf5ef2aSThomas Huth } 289fcf5ef2aSThomas Huth } 290fcf5ef2aSThomas Huth 291fcf5ef2aSThomas Huth static void kvm_arm_devlistener_del(MemoryListener *listener, 292fcf5ef2aSThomas Huth MemoryRegionSection *section) 293fcf5ef2aSThomas Huth { 294fcf5ef2aSThomas Huth KVMDevice *kd; 295fcf5ef2aSThomas Huth 296fcf5ef2aSThomas Huth QSLIST_FOREACH(kd, &kvm_devices_head, entries) { 297fcf5ef2aSThomas Huth if (section->mr == kd->mr) { 298fcf5ef2aSThomas Huth kd->kda.addr = -1; 299fcf5ef2aSThomas Huth } 300fcf5ef2aSThomas Huth } 301fcf5ef2aSThomas Huth } 302fcf5ef2aSThomas Huth 303fcf5ef2aSThomas Huth static MemoryListener devlistener = { 304fcf5ef2aSThomas Huth .region_add = kvm_arm_devlistener_add, 305fcf5ef2aSThomas Huth .region_del = kvm_arm_devlistener_del, 306fcf5ef2aSThomas Huth }; 307fcf5ef2aSThomas Huth 308fcf5ef2aSThomas Huth static void kvm_arm_set_device_addr(KVMDevice *kd) 309fcf5ef2aSThomas Huth { 310fcf5ef2aSThomas Huth struct kvm_device_attr *attr = &kd->kdattr; 311fcf5ef2aSThomas Huth int ret; 312fcf5ef2aSThomas Huth 313fcf5ef2aSThomas Huth /* If the device control API is available and we have a device fd on the 314fcf5ef2aSThomas Huth * KVMDevice struct, let's use the newer API 315fcf5ef2aSThomas Huth */ 316fcf5ef2aSThomas Huth if (kd->dev_fd >= 0) { 317fcf5ef2aSThomas Huth uint64_t addr = kd->kda.addr; 31819d1bd0bSEric Auger 31919d1bd0bSEric Auger addr |= kd->kda_addr_ormask; 320fcf5ef2aSThomas Huth attr->addr = (uintptr_t)&addr; 321fcf5ef2aSThomas Huth ret = kvm_device_ioctl(kd->dev_fd, KVM_SET_DEVICE_ATTR, attr); 322fcf5ef2aSThomas Huth } else { 323fcf5ef2aSThomas Huth ret = kvm_vm_ioctl(kvm_state, KVM_ARM_SET_DEVICE_ADDR, &kd->kda); 324fcf5ef2aSThomas Huth } 325fcf5ef2aSThomas Huth 326fcf5ef2aSThomas Huth if (ret < 0) { 327fcf5ef2aSThomas Huth fprintf(stderr, "Failed to set device address: %s\n", 328fcf5ef2aSThomas Huth strerror(-ret)); 329fcf5ef2aSThomas Huth abort(); 330fcf5ef2aSThomas Huth } 331fcf5ef2aSThomas Huth } 332fcf5ef2aSThomas Huth 333fcf5ef2aSThomas Huth static void kvm_arm_machine_init_done(Notifier *notifier, void *data) 334fcf5ef2aSThomas Huth { 335fcf5ef2aSThomas Huth KVMDevice *kd, *tkd; 336fcf5ef2aSThomas Huth 337fcf5ef2aSThomas Huth QSLIST_FOREACH_SAFE(kd, &kvm_devices_head, entries, tkd) { 338fcf5ef2aSThomas Huth if (kd->kda.addr != -1) { 339fcf5ef2aSThomas Huth kvm_arm_set_device_addr(kd); 340fcf5ef2aSThomas Huth } 341fcf5ef2aSThomas Huth memory_region_unref(kd->mr); 3425ff9aaabSZheng Xiang QSLIST_REMOVE_HEAD(&kvm_devices_head, entries); 343fcf5ef2aSThomas Huth g_free(kd); 344fcf5ef2aSThomas Huth } 3450bbe4354SPeter Xu memory_listener_unregister(&devlistener); 346fcf5ef2aSThomas Huth } 347fcf5ef2aSThomas Huth 348fcf5ef2aSThomas Huth static Notifier notify = { 349fcf5ef2aSThomas Huth .notify = kvm_arm_machine_init_done, 350fcf5ef2aSThomas Huth }; 351fcf5ef2aSThomas Huth 352fcf5ef2aSThomas Huth void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, 35319d1bd0bSEric Auger uint64_t attr, int dev_fd, uint64_t addr_ormask) 354fcf5ef2aSThomas Huth { 355fcf5ef2aSThomas Huth KVMDevice *kd; 356fcf5ef2aSThomas Huth 357fcf5ef2aSThomas Huth if (!kvm_irqchip_in_kernel()) { 358fcf5ef2aSThomas Huth return; 359fcf5ef2aSThomas Huth } 360fcf5ef2aSThomas Huth 361fcf5ef2aSThomas Huth if (QSLIST_EMPTY(&kvm_devices_head)) { 362fcf5ef2aSThomas Huth memory_listener_register(&devlistener, &address_space_memory); 363fcf5ef2aSThomas Huth qemu_add_machine_init_done_notifier(¬ify); 364fcf5ef2aSThomas Huth } 365fcf5ef2aSThomas Huth kd = g_new0(KVMDevice, 1); 366fcf5ef2aSThomas Huth kd->mr = mr; 367fcf5ef2aSThomas Huth kd->kda.id = devid; 368fcf5ef2aSThomas Huth kd->kda.addr = -1; 369fcf5ef2aSThomas Huth kd->kdattr.flags = 0; 370fcf5ef2aSThomas Huth kd->kdattr.group = group; 371fcf5ef2aSThomas Huth kd->kdattr.attr = attr; 372fcf5ef2aSThomas Huth kd->dev_fd = dev_fd; 37319d1bd0bSEric Auger kd->kda_addr_ormask = addr_ormask; 374fcf5ef2aSThomas Huth QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries); 375fcf5ef2aSThomas Huth memory_region_ref(kd->mr); 376fcf5ef2aSThomas Huth } 377fcf5ef2aSThomas Huth 378fcf5ef2aSThomas Huth static int compare_u64(const void *a, const void *b) 379fcf5ef2aSThomas Huth { 380fcf5ef2aSThomas Huth if (*(uint64_t *)a > *(uint64_t *)b) { 381fcf5ef2aSThomas Huth return 1; 382fcf5ef2aSThomas Huth } 383fcf5ef2aSThomas Huth if (*(uint64_t *)a < *(uint64_t *)b) { 384fcf5ef2aSThomas Huth return -1; 385fcf5ef2aSThomas Huth } 386fcf5ef2aSThomas Huth return 0; 387fcf5ef2aSThomas Huth } 388fcf5ef2aSThomas Huth 389e5ac4200SAndrew Jones /* 390e5ac4200SAndrew Jones * cpreg_values are sorted in ascending order by KVM register ID 391e5ac4200SAndrew Jones * (see kvm_arm_init_cpreg_list). This allows us to cheaply find 392e5ac4200SAndrew Jones * the storage for a KVM register by ID with a binary search. 393e5ac4200SAndrew Jones */ 394e5ac4200SAndrew Jones static uint64_t *kvm_arm_get_cpreg_ptr(ARMCPU *cpu, uint64_t regidx) 395e5ac4200SAndrew Jones { 396e5ac4200SAndrew Jones uint64_t *res; 397e5ac4200SAndrew Jones 398e5ac4200SAndrew Jones res = bsearch(®idx, cpu->cpreg_indexes, cpu->cpreg_array_len, 399e5ac4200SAndrew Jones sizeof(uint64_t), compare_u64); 400e5ac4200SAndrew Jones assert(res); 401e5ac4200SAndrew Jones 402e5ac4200SAndrew Jones return &cpu->cpreg_values[res - cpu->cpreg_indexes]; 403e5ac4200SAndrew Jones } 404e5ac4200SAndrew Jones 405c8a44709SDongjiu Geng /* Initialize the ARMCPU cpreg list according to the kernel's 406fcf5ef2aSThomas Huth * definition of what CPU registers it knows about (and throw away 407fcf5ef2aSThomas Huth * the previous TCG-created cpreg list). 408fcf5ef2aSThomas Huth */ 409fcf5ef2aSThomas Huth int kvm_arm_init_cpreg_list(ARMCPU *cpu) 410fcf5ef2aSThomas Huth { 411fcf5ef2aSThomas Huth struct kvm_reg_list rl; 412fcf5ef2aSThomas Huth struct kvm_reg_list *rlp; 413fcf5ef2aSThomas Huth int i, ret, arraylen; 414fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 415fcf5ef2aSThomas Huth 416fcf5ef2aSThomas Huth rl.n = 0; 417fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, &rl); 418fcf5ef2aSThomas Huth if (ret != -E2BIG) { 419fcf5ef2aSThomas Huth return ret; 420fcf5ef2aSThomas Huth } 421fcf5ef2aSThomas Huth rlp = g_malloc(sizeof(struct kvm_reg_list) + rl.n * sizeof(uint64_t)); 422fcf5ef2aSThomas Huth rlp->n = rl.n; 423fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, rlp); 424fcf5ef2aSThomas Huth if (ret) { 425fcf5ef2aSThomas Huth goto out; 426fcf5ef2aSThomas Huth } 427fcf5ef2aSThomas Huth /* Sort the list we get back from the kernel, since cpreg_tuples 428fcf5ef2aSThomas Huth * must be in strictly ascending order. 429fcf5ef2aSThomas Huth */ 430fcf5ef2aSThomas Huth qsort(&rlp->reg, rlp->n, sizeof(rlp->reg[0]), compare_u64); 431fcf5ef2aSThomas Huth 432fcf5ef2aSThomas Huth for (i = 0, arraylen = 0; i < rlp->n; i++) { 433fcf5ef2aSThomas Huth if (!kvm_arm_reg_syncs_via_cpreg_list(rlp->reg[i])) { 434fcf5ef2aSThomas Huth continue; 435fcf5ef2aSThomas Huth } 436fcf5ef2aSThomas Huth switch (rlp->reg[i] & KVM_REG_SIZE_MASK) { 437fcf5ef2aSThomas Huth case KVM_REG_SIZE_U32: 438fcf5ef2aSThomas Huth case KVM_REG_SIZE_U64: 439fcf5ef2aSThomas Huth break; 440fcf5ef2aSThomas Huth default: 441fcf5ef2aSThomas Huth fprintf(stderr, "Can't handle size of register in kernel list\n"); 442fcf5ef2aSThomas Huth ret = -EINVAL; 443fcf5ef2aSThomas Huth goto out; 444fcf5ef2aSThomas Huth } 445fcf5ef2aSThomas Huth 446fcf5ef2aSThomas Huth arraylen++; 447fcf5ef2aSThomas Huth } 448fcf5ef2aSThomas Huth 449fcf5ef2aSThomas Huth cpu->cpreg_indexes = g_renew(uint64_t, cpu->cpreg_indexes, arraylen); 450fcf5ef2aSThomas Huth cpu->cpreg_values = g_renew(uint64_t, cpu->cpreg_values, arraylen); 451fcf5ef2aSThomas Huth cpu->cpreg_vmstate_indexes = g_renew(uint64_t, cpu->cpreg_vmstate_indexes, 452fcf5ef2aSThomas Huth arraylen); 453fcf5ef2aSThomas Huth cpu->cpreg_vmstate_values = g_renew(uint64_t, cpu->cpreg_vmstate_values, 454fcf5ef2aSThomas Huth arraylen); 455fcf5ef2aSThomas Huth cpu->cpreg_array_len = arraylen; 456fcf5ef2aSThomas Huth cpu->cpreg_vmstate_array_len = arraylen; 457fcf5ef2aSThomas Huth 458fcf5ef2aSThomas Huth for (i = 0, arraylen = 0; i < rlp->n; i++) { 459fcf5ef2aSThomas Huth uint64_t regidx = rlp->reg[i]; 460fcf5ef2aSThomas Huth if (!kvm_arm_reg_syncs_via_cpreg_list(regidx)) { 461fcf5ef2aSThomas Huth continue; 462fcf5ef2aSThomas Huth } 463fcf5ef2aSThomas Huth cpu->cpreg_indexes[arraylen] = regidx; 464fcf5ef2aSThomas Huth arraylen++; 465fcf5ef2aSThomas Huth } 466fcf5ef2aSThomas Huth assert(cpu->cpreg_array_len == arraylen); 467fcf5ef2aSThomas Huth 468fcf5ef2aSThomas Huth if (!write_kvmstate_to_list(cpu)) { 469fcf5ef2aSThomas Huth /* Shouldn't happen unless kernel is inconsistent about 470fcf5ef2aSThomas Huth * what registers exist. 471fcf5ef2aSThomas Huth */ 472fcf5ef2aSThomas Huth fprintf(stderr, "Initial read of kernel register state failed\n"); 473fcf5ef2aSThomas Huth ret = -EINVAL; 474fcf5ef2aSThomas Huth goto out; 475fcf5ef2aSThomas Huth } 476fcf5ef2aSThomas Huth 477fcf5ef2aSThomas Huth out: 478fcf5ef2aSThomas Huth g_free(rlp); 479fcf5ef2aSThomas Huth return ret; 480fcf5ef2aSThomas Huth } 481fcf5ef2aSThomas Huth 482fcf5ef2aSThomas Huth bool write_kvmstate_to_list(ARMCPU *cpu) 483fcf5ef2aSThomas Huth { 484fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 485fcf5ef2aSThomas Huth int i; 486fcf5ef2aSThomas Huth bool ok = true; 487fcf5ef2aSThomas Huth 488fcf5ef2aSThomas Huth for (i = 0; i < cpu->cpreg_array_len; i++) { 489fcf5ef2aSThomas Huth struct kvm_one_reg r; 490fcf5ef2aSThomas Huth uint64_t regidx = cpu->cpreg_indexes[i]; 491fcf5ef2aSThomas Huth uint32_t v32; 492fcf5ef2aSThomas Huth int ret; 493fcf5ef2aSThomas Huth 494fcf5ef2aSThomas Huth r.id = regidx; 495fcf5ef2aSThomas Huth 496fcf5ef2aSThomas Huth switch (regidx & KVM_REG_SIZE_MASK) { 497fcf5ef2aSThomas Huth case KVM_REG_SIZE_U32: 498fcf5ef2aSThomas Huth r.addr = (uintptr_t)&v32; 499fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r); 500fcf5ef2aSThomas Huth if (!ret) { 501fcf5ef2aSThomas Huth cpu->cpreg_values[i] = v32; 502fcf5ef2aSThomas Huth } 503fcf5ef2aSThomas Huth break; 504fcf5ef2aSThomas Huth case KVM_REG_SIZE_U64: 505fcf5ef2aSThomas Huth r.addr = (uintptr_t)(cpu->cpreg_values + i); 506fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r); 507fcf5ef2aSThomas Huth break; 508fcf5ef2aSThomas Huth default: 509fcf5ef2aSThomas Huth abort(); 510fcf5ef2aSThomas Huth } 511fcf5ef2aSThomas Huth if (ret) { 512fcf5ef2aSThomas Huth ok = false; 513fcf5ef2aSThomas Huth } 514fcf5ef2aSThomas Huth } 515fcf5ef2aSThomas Huth return ok; 516fcf5ef2aSThomas Huth } 517fcf5ef2aSThomas Huth 518fcf5ef2aSThomas Huth bool write_list_to_kvmstate(ARMCPU *cpu, int level) 519fcf5ef2aSThomas Huth { 520fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 521fcf5ef2aSThomas Huth int i; 522fcf5ef2aSThomas Huth bool ok = true; 523fcf5ef2aSThomas Huth 524fcf5ef2aSThomas Huth for (i = 0; i < cpu->cpreg_array_len; i++) { 525fcf5ef2aSThomas Huth struct kvm_one_reg r; 526fcf5ef2aSThomas Huth uint64_t regidx = cpu->cpreg_indexes[i]; 527fcf5ef2aSThomas Huth uint32_t v32; 528fcf5ef2aSThomas Huth int ret; 529fcf5ef2aSThomas Huth 530fcf5ef2aSThomas Huth if (kvm_arm_cpreg_level(regidx) > level) { 531fcf5ef2aSThomas Huth continue; 532fcf5ef2aSThomas Huth } 533fcf5ef2aSThomas Huth 534fcf5ef2aSThomas Huth r.id = regidx; 535fcf5ef2aSThomas Huth switch (regidx & KVM_REG_SIZE_MASK) { 536fcf5ef2aSThomas Huth case KVM_REG_SIZE_U32: 537fcf5ef2aSThomas Huth v32 = cpu->cpreg_values[i]; 538fcf5ef2aSThomas Huth r.addr = (uintptr_t)&v32; 539fcf5ef2aSThomas Huth break; 540fcf5ef2aSThomas Huth case KVM_REG_SIZE_U64: 541fcf5ef2aSThomas Huth r.addr = (uintptr_t)(cpu->cpreg_values + i); 542fcf5ef2aSThomas Huth break; 543fcf5ef2aSThomas Huth default: 544fcf5ef2aSThomas Huth abort(); 545fcf5ef2aSThomas Huth } 546fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r); 547fcf5ef2aSThomas Huth if (ret) { 548fcf5ef2aSThomas Huth /* We might fail for "unknown register" and also for 549fcf5ef2aSThomas Huth * "you tried to set a register which is constant with 550fcf5ef2aSThomas Huth * a different value from what it actually contains". 551fcf5ef2aSThomas Huth */ 552fcf5ef2aSThomas Huth ok = false; 553fcf5ef2aSThomas Huth } 554fcf5ef2aSThomas Huth } 555fcf5ef2aSThomas Huth return ok; 556fcf5ef2aSThomas Huth } 557fcf5ef2aSThomas Huth 558e5ac4200SAndrew Jones void kvm_arm_cpu_pre_save(ARMCPU *cpu) 559e5ac4200SAndrew Jones { 560e5ac4200SAndrew Jones /* KVM virtual time adjustment */ 561e5ac4200SAndrew Jones if (cpu->kvm_vtime_dirty) { 562e5ac4200SAndrew Jones *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT) = cpu->kvm_vtime; 563e5ac4200SAndrew Jones } 564e5ac4200SAndrew Jones } 565e5ac4200SAndrew Jones 566e5ac4200SAndrew Jones void kvm_arm_cpu_post_load(ARMCPU *cpu) 567e5ac4200SAndrew Jones { 568e5ac4200SAndrew Jones /* KVM virtual time adjustment */ 569e5ac4200SAndrew Jones if (cpu->kvm_adjvtime) { 570e5ac4200SAndrew Jones cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT); 571e5ac4200SAndrew Jones cpu->kvm_vtime_dirty = true; 572e5ac4200SAndrew Jones } 573e5ac4200SAndrew Jones } 574e5ac4200SAndrew Jones 575fcf5ef2aSThomas Huth void kvm_arm_reset_vcpu(ARMCPU *cpu) 576fcf5ef2aSThomas Huth { 577fcf5ef2aSThomas Huth int ret; 578fcf5ef2aSThomas Huth 579fcf5ef2aSThomas Huth /* Re-init VCPU so that all registers are set to 580fcf5ef2aSThomas Huth * their respective reset values. 581fcf5ef2aSThomas Huth */ 582fcf5ef2aSThomas Huth ret = kvm_arm_vcpu_init(CPU(cpu)); 583fcf5ef2aSThomas Huth if (ret < 0) { 584fcf5ef2aSThomas Huth fprintf(stderr, "kvm_arm_vcpu_init failed: %s\n", strerror(-ret)); 585fcf5ef2aSThomas Huth abort(); 586fcf5ef2aSThomas Huth } 587fcf5ef2aSThomas Huth if (!write_kvmstate_to_list(cpu)) { 588fcf5ef2aSThomas Huth fprintf(stderr, "write_kvmstate_to_list failed\n"); 589fcf5ef2aSThomas Huth abort(); 590fcf5ef2aSThomas Huth } 591b698e4eeSPeter Maydell /* 592b698e4eeSPeter Maydell * Sync the reset values also into the CPUState. This is necessary 593b698e4eeSPeter Maydell * because the next thing we do will be a kvm_arch_put_registers() 594b698e4eeSPeter Maydell * which will update the list values from the CPUState before copying 595b698e4eeSPeter Maydell * the list values back to KVM. It's OK to ignore failure returns here 596b698e4eeSPeter Maydell * for the same reason we do so in kvm_arch_get_registers(). 597b698e4eeSPeter Maydell */ 598b698e4eeSPeter Maydell write_list_to_cpustate(cpu); 599fcf5ef2aSThomas Huth } 600fcf5ef2aSThomas Huth 601fcf5ef2aSThomas Huth /* 602fcf5ef2aSThomas Huth * Update KVM's MP_STATE based on what QEMU thinks it is 603fcf5ef2aSThomas Huth */ 604fcf5ef2aSThomas Huth int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu) 605fcf5ef2aSThomas Huth { 606fcf5ef2aSThomas Huth if (cap_has_mp_state) { 607fcf5ef2aSThomas Huth struct kvm_mp_state mp_state = { 608062ba099SAlex Bennée .mp_state = (cpu->power_state == PSCI_OFF) ? 609062ba099SAlex Bennée KVM_MP_STATE_STOPPED : KVM_MP_STATE_RUNNABLE 610fcf5ef2aSThomas Huth }; 611fcf5ef2aSThomas Huth int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state); 612fcf5ef2aSThomas Huth if (ret) { 613fcf5ef2aSThomas Huth fprintf(stderr, "%s: failed to set MP_STATE %d/%s\n", 614fcf5ef2aSThomas Huth __func__, ret, strerror(-ret)); 615fcf5ef2aSThomas Huth return -1; 616fcf5ef2aSThomas Huth } 617fcf5ef2aSThomas Huth } 618fcf5ef2aSThomas Huth 619fcf5ef2aSThomas Huth return 0; 620fcf5ef2aSThomas Huth } 621fcf5ef2aSThomas Huth 622fcf5ef2aSThomas Huth /* 623fcf5ef2aSThomas Huth * Sync the KVM MP_STATE into QEMU 624fcf5ef2aSThomas Huth */ 625fcf5ef2aSThomas Huth int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu) 626fcf5ef2aSThomas Huth { 627fcf5ef2aSThomas Huth if (cap_has_mp_state) { 628fcf5ef2aSThomas Huth struct kvm_mp_state mp_state; 629fcf5ef2aSThomas Huth int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MP_STATE, &mp_state); 630fcf5ef2aSThomas Huth if (ret) { 631fcf5ef2aSThomas Huth fprintf(stderr, "%s: failed to get MP_STATE %d/%s\n", 632fcf5ef2aSThomas Huth __func__, ret, strerror(-ret)); 633fcf5ef2aSThomas Huth abort(); 634fcf5ef2aSThomas Huth } 635062ba099SAlex Bennée cpu->power_state = (mp_state.mp_state == KVM_MP_STATE_STOPPED) ? 636062ba099SAlex Bennée PSCI_OFF : PSCI_ON; 637fcf5ef2aSThomas Huth } 638fcf5ef2aSThomas Huth 639fcf5ef2aSThomas Huth return 0; 640fcf5ef2aSThomas Huth } 641fcf5ef2aSThomas Huth 642e5ac4200SAndrew Jones void kvm_arm_get_virtual_time(CPUState *cs) 643e5ac4200SAndrew Jones { 644e5ac4200SAndrew Jones ARMCPU *cpu = ARM_CPU(cs); 645e5ac4200SAndrew Jones struct kvm_one_reg reg = { 646e5ac4200SAndrew Jones .id = KVM_REG_ARM_TIMER_CNT, 647e5ac4200SAndrew Jones .addr = (uintptr_t)&cpu->kvm_vtime, 648e5ac4200SAndrew Jones }; 649e5ac4200SAndrew Jones int ret; 650e5ac4200SAndrew Jones 651e5ac4200SAndrew Jones if (cpu->kvm_vtime_dirty) { 652e5ac4200SAndrew Jones return; 653e5ac4200SAndrew Jones } 654e5ac4200SAndrew Jones 655e5ac4200SAndrew Jones ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); 656e5ac4200SAndrew Jones if (ret) { 657e5ac4200SAndrew Jones error_report("Failed to get KVM_REG_ARM_TIMER_CNT"); 658e5ac4200SAndrew Jones abort(); 659e5ac4200SAndrew Jones } 660e5ac4200SAndrew Jones 661e5ac4200SAndrew Jones cpu->kvm_vtime_dirty = true; 662e5ac4200SAndrew Jones } 663e5ac4200SAndrew Jones 664e5ac4200SAndrew Jones void kvm_arm_put_virtual_time(CPUState *cs) 665e5ac4200SAndrew Jones { 666e5ac4200SAndrew Jones ARMCPU *cpu = ARM_CPU(cs); 667e5ac4200SAndrew Jones struct kvm_one_reg reg = { 668e5ac4200SAndrew Jones .id = KVM_REG_ARM_TIMER_CNT, 669e5ac4200SAndrew Jones .addr = (uintptr_t)&cpu->kvm_vtime, 670e5ac4200SAndrew Jones }; 671e5ac4200SAndrew Jones int ret; 672e5ac4200SAndrew Jones 673e5ac4200SAndrew Jones if (!cpu->kvm_vtime_dirty) { 674e5ac4200SAndrew Jones return; 675e5ac4200SAndrew Jones } 676e5ac4200SAndrew Jones 677e5ac4200SAndrew Jones ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); 678e5ac4200SAndrew Jones if (ret) { 679e5ac4200SAndrew Jones error_report("Failed to set KVM_REG_ARM_TIMER_CNT"); 680e5ac4200SAndrew Jones abort(); 681e5ac4200SAndrew Jones } 682e5ac4200SAndrew Jones 683e5ac4200SAndrew Jones cpu->kvm_vtime_dirty = false; 684e5ac4200SAndrew Jones } 685e5ac4200SAndrew Jones 686202ccb6bSDongjiu Geng int kvm_put_vcpu_events(ARMCPU *cpu) 687202ccb6bSDongjiu Geng { 688202ccb6bSDongjiu Geng CPUARMState *env = &cpu->env; 689202ccb6bSDongjiu Geng struct kvm_vcpu_events events; 690202ccb6bSDongjiu Geng int ret; 691202ccb6bSDongjiu Geng 692202ccb6bSDongjiu Geng if (!kvm_has_vcpu_events()) { 693202ccb6bSDongjiu Geng return 0; 694202ccb6bSDongjiu Geng } 695202ccb6bSDongjiu Geng 696202ccb6bSDongjiu Geng memset(&events, 0, sizeof(events)); 697202ccb6bSDongjiu Geng events.exception.serror_pending = env->serror.pending; 698202ccb6bSDongjiu Geng 699202ccb6bSDongjiu Geng /* Inject SError to guest with specified syndrome if host kernel 700202ccb6bSDongjiu Geng * supports it, otherwise inject SError without syndrome. 701202ccb6bSDongjiu Geng */ 702202ccb6bSDongjiu Geng if (cap_has_inject_serror_esr) { 703202ccb6bSDongjiu Geng events.exception.serror_has_esr = env->serror.has_esr; 704202ccb6bSDongjiu Geng events.exception.serror_esr = env->serror.esr; 705202ccb6bSDongjiu Geng } 706202ccb6bSDongjiu Geng 707202ccb6bSDongjiu Geng ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_VCPU_EVENTS, &events); 708202ccb6bSDongjiu Geng if (ret) { 709202ccb6bSDongjiu Geng error_report("failed to put vcpu events"); 710202ccb6bSDongjiu Geng } 711202ccb6bSDongjiu Geng 712202ccb6bSDongjiu Geng return ret; 713202ccb6bSDongjiu Geng } 714202ccb6bSDongjiu Geng 715202ccb6bSDongjiu Geng int kvm_get_vcpu_events(ARMCPU *cpu) 716202ccb6bSDongjiu Geng { 717202ccb6bSDongjiu Geng CPUARMState *env = &cpu->env; 718202ccb6bSDongjiu Geng struct kvm_vcpu_events events; 719202ccb6bSDongjiu Geng int ret; 720202ccb6bSDongjiu Geng 721202ccb6bSDongjiu Geng if (!kvm_has_vcpu_events()) { 722202ccb6bSDongjiu Geng return 0; 723202ccb6bSDongjiu Geng } 724202ccb6bSDongjiu Geng 725202ccb6bSDongjiu Geng memset(&events, 0, sizeof(events)); 726202ccb6bSDongjiu Geng ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_VCPU_EVENTS, &events); 727202ccb6bSDongjiu Geng if (ret) { 728202ccb6bSDongjiu Geng error_report("failed to get vcpu events"); 729202ccb6bSDongjiu Geng return ret; 730202ccb6bSDongjiu Geng } 731202ccb6bSDongjiu Geng 732202ccb6bSDongjiu Geng env->serror.pending = events.exception.serror_pending; 733202ccb6bSDongjiu Geng env->serror.has_esr = events.exception.serror_has_esr; 734202ccb6bSDongjiu Geng env->serror.esr = events.exception.serror_esr; 735202ccb6bSDongjiu Geng 736202ccb6bSDongjiu Geng return 0; 737202ccb6bSDongjiu Geng } 738202ccb6bSDongjiu Geng 739fcf5ef2aSThomas Huth void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 740fcf5ef2aSThomas Huth { 741fcf5ef2aSThomas Huth } 742fcf5ef2aSThomas Huth 743fcf5ef2aSThomas Huth MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 744fcf5ef2aSThomas Huth { 7455d721b78SAlexander Graf ARMCPU *cpu; 7465d721b78SAlexander Graf uint32_t switched_level; 7475d721b78SAlexander Graf 7485d721b78SAlexander Graf if (kvm_irqchip_in_kernel()) { 7495d721b78SAlexander Graf /* 7505d721b78SAlexander Graf * We only need to sync timer states with user-space interrupt 7515d721b78SAlexander Graf * controllers, so return early and save cycles if we don't. 7525d721b78SAlexander Graf */ 7535d721b78SAlexander Graf return MEMTXATTRS_UNSPECIFIED; 7545d721b78SAlexander Graf } 7555d721b78SAlexander Graf 7565d721b78SAlexander Graf cpu = ARM_CPU(cs); 7575d721b78SAlexander Graf 7585d721b78SAlexander Graf /* Synchronize our shadowed in-kernel device irq lines with the kvm ones */ 7595d721b78SAlexander Graf if (run->s.regs.device_irq_level != cpu->device_irq_level) { 7605d721b78SAlexander Graf switched_level = cpu->device_irq_level ^ run->s.regs.device_irq_level; 7615d721b78SAlexander Graf 7625d721b78SAlexander Graf qemu_mutex_lock_iothread(); 7635d721b78SAlexander Graf 7645d721b78SAlexander Graf if (switched_level & KVM_ARM_DEV_EL1_VTIMER) { 7655d721b78SAlexander Graf qemu_set_irq(cpu->gt_timer_outputs[GTIMER_VIRT], 7665d721b78SAlexander Graf !!(run->s.regs.device_irq_level & 7675d721b78SAlexander Graf KVM_ARM_DEV_EL1_VTIMER)); 7685d721b78SAlexander Graf switched_level &= ~KVM_ARM_DEV_EL1_VTIMER; 7695d721b78SAlexander Graf } 7705d721b78SAlexander Graf 7715d721b78SAlexander Graf if (switched_level & KVM_ARM_DEV_EL1_PTIMER) { 7725d721b78SAlexander Graf qemu_set_irq(cpu->gt_timer_outputs[GTIMER_PHYS], 7735d721b78SAlexander Graf !!(run->s.regs.device_irq_level & 7745d721b78SAlexander Graf KVM_ARM_DEV_EL1_PTIMER)); 7755d721b78SAlexander Graf switched_level &= ~KVM_ARM_DEV_EL1_PTIMER; 7765d721b78SAlexander Graf } 7775d721b78SAlexander Graf 778b1659527SAndrew Jones if (switched_level & KVM_ARM_DEV_PMU) { 779b1659527SAndrew Jones qemu_set_irq(cpu->pmu_interrupt, 780b1659527SAndrew Jones !!(run->s.regs.device_irq_level & KVM_ARM_DEV_PMU)); 781b1659527SAndrew Jones switched_level &= ~KVM_ARM_DEV_PMU; 782b1659527SAndrew Jones } 7835d721b78SAlexander Graf 7845d721b78SAlexander Graf if (switched_level) { 7855d721b78SAlexander Graf qemu_log_mask(LOG_UNIMP, "%s: unhandled in-kernel device IRQ %x\n", 7865d721b78SAlexander Graf __func__, switched_level); 7875d721b78SAlexander Graf } 7885d721b78SAlexander Graf 7895d721b78SAlexander Graf /* We also mark unknown levels as processed to not waste cycles */ 7905d721b78SAlexander Graf cpu->device_irq_level = run->s.regs.device_irq_level; 7915d721b78SAlexander Graf qemu_mutex_unlock_iothread(); 7925d721b78SAlexander Graf } 7935d721b78SAlexander Graf 794fcf5ef2aSThomas Huth return MEMTXATTRS_UNSPECIFIED; 795fcf5ef2aSThomas Huth } 796fcf5ef2aSThomas Huth 797e5ac4200SAndrew Jones void kvm_arm_vm_state_change(void *opaque, int running, RunState state) 798e5ac4200SAndrew Jones { 799e5ac4200SAndrew Jones CPUState *cs = opaque; 800e5ac4200SAndrew Jones ARMCPU *cpu = ARM_CPU(cs); 801e5ac4200SAndrew Jones 802e5ac4200SAndrew Jones if (running) { 803e5ac4200SAndrew Jones if (cpu->kvm_adjvtime) { 804e5ac4200SAndrew Jones kvm_arm_put_virtual_time(cs); 805e5ac4200SAndrew Jones } 806e5ac4200SAndrew Jones } else { 807e5ac4200SAndrew Jones if (cpu->kvm_adjvtime) { 808e5ac4200SAndrew Jones kvm_arm_get_virtual_time(cs); 809e5ac4200SAndrew Jones } 810e5ac4200SAndrew Jones } 811e5ac4200SAndrew Jones } 812fcf5ef2aSThomas Huth 813fcf5ef2aSThomas Huth int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 814fcf5ef2aSThomas Huth { 815fcf5ef2aSThomas Huth int ret = 0; 816fcf5ef2aSThomas Huth 817fcf5ef2aSThomas Huth switch (run->exit_reason) { 818fcf5ef2aSThomas Huth case KVM_EXIT_DEBUG: 819fcf5ef2aSThomas Huth if (kvm_arm_handle_debug(cs, &run->debug.arch)) { 820fcf5ef2aSThomas Huth ret = EXCP_DEBUG; 821fcf5ef2aSThomas Huth } /* otherwise return to guest */ 822fcf5ef2aSThomas Huth break; 823fcf5ef2aSThomas Huth default: 824fcf5ef2aSThomas Huth qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", 825fcf5ef2aSThomas Huth __func__, run->exit_reason); 826fcf5ef2aSThomas Huth break; 827fcf5ef2aSThomas Huth } 828fcf5ef2aSThomas Huth return ret; 829fcf5ef2aSThomas Huth } 830fcf5ef2aSThomas Huth 831fcf5ef2aSThomas Huth bool kvm_arch_stop_on_emulation_error(CPUState *cs) 832fcf5ef2aSThomas Huth { 833fcf5ef2aSThomas Huth return true; 834fcf5ef2aSThomas Huth } 835fcf5ef2aSThomas Huth 836fcf5ef2aSThomas Huth int kvm_arch_process_async_events(CPUState *cs) 837fcf5ef2aSThomas Huth { 838fcf5ef2aSThomas Huth return 0; 839fcf5ef2aSThomas Huth } 840fcf5ef2aSThomas Huth 841fcf5ef2aSThomas Huth /* The #ifdef protections are until 32bit headers are imported and can 842fcf5ef2aSThomas Huth * be removed once both 32 and 64 bit reach feature parity. 843fcf5ef2aSThomas Huth */ 844fcf5ef2aSThomas Huth void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) 845fcf5ef2aSThomas Huth { 846fcf5ef2aSThomas Huth #ifdef KVM_GUESTDBG_USE_SW_BP 847fcf5ef2aSThomas Huth if (kvm_sw_breakpoints_active(cs)) { 848fcf5ef2aSThomas Huth dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; 849fcf5ef2aSThomas Huth } 850fcf5ef2aSThomas Huth #endif 851fcf5ef2aSThomas Huth #ifdef KVM_GUESTDBG_USE_HW 852fcf5ef2aSThomas Huth if (kvm_arm_hw_debug_active(cs)) { 853fcf5ef2aSThomas Huth dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW; 854fcf5ef2aSThomas Huth kvm_arm_copy_hw_debug_data(&dbg->arch); 855fcf5ef2aSThomas Huth } 856fcf5ef2aSThomas Huth #endif 857fcf5ef2aSThomas Huth } 858fcf5ef2aSThomas Huth 859fcf5ef2aSThomas Huth void kvm_arch_init_irq_routing(KVMState *s) 860fcf5ef2aSThomas Huth { 861fcf5ef2aSThomas Huth } 862fcf5ef2aSThomas Huth 8634376c40dSPaolo Bonzini int kvm_arch_irqchip_create(KVMState *s) 864fcf5ef2aSThomas Huth { 8654376c40dSPaolo Bonzini if (kvm_kernel_irqchip_split()) { 866fcf5ef2aSThomas Huth perror("-machine kernel_irqchip=split is not supported on ARM."); 867fcf5ef2aSThomas Huth exit(1); 868fcf5ef2aSThomas Huth } 869fcf5ef2aSThomas Huth 870fcf5ef2aSThomas Huth /* If we can create the VGIC using the newer device control API, we 871fcf5ef2aSThomas Huth * let the device do this when it initializes itself, otherwise we 872fcf5ef2aSThomas Huth * fall back to the old API */ 873fcf5ef2aSThomas Huth return kvm_check_extension(s, KVM_CAP_DEVICE_CTRL); 874fcf5ef2aSThomas Huth } 875fcf5ef2aSThomas Huth 876fcf5ef2aSThomas Huth int kvm_arm_vgic_probe(void) 877fcf5ef2aSThomas Huth { 878d45efe47SEric Auger int val = 0; 879d45efe47SEric Auger 880fcf5ef2aSThomas Huth if (kvm_create_device(kvm_state, 881fcf5ef2aSThomas Huth KVM_DEV_TYPE_ARM_VGIC_V3, true) == 0) { 882d45efe47SEric Auger val |= KVM_ARM_VGIC_V3; 883fcf5ef2aSThomas Huth } 884d45efe47SEric Auger if (kvm_create_device(kvm_state, 885d45efe47SEric Auger KVM_DEV_TYPE_ARM_VGIC_V2, true) == 0) { 886d45efe47SEric Auger val |= KVM_ARM_VGIC_V2; 887d45efe47SEric Auger } 888d45efe47SEric Auger return val; 889fcf5ef2aSThomas Huth } 890fcf5ef2aSThomas Huth 891f6530926SEric Auger int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level) 892f6530926SEric Auger { 893f6530926SEric Auger int kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT) | irq; 894f6530926SEric Auger int cpu_idx1 = cpu % 256; 895f6530926SEric Auger int cpu_idx2 = cpu / 256; 896f6530926SEric Auger 897f6530926SEric Auger kvm_irq |= (cpu_idx1 << KVM_ARM_IRQ_VCPU_SHIFT) | 898f6530926SEric Auger (cpu_idx2 << KVM_ARM_IRQ_VCPU2_SHIFT); 899f6530926SEric Auger 900f6530926SEric Auger return kvm_set_irq(kvm_state, kvm_irq, !!level); 901f6530926SEric Auger } 902f6530926SEric Auger 903fcf5ef2aSThomas Huth int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 904fcf5ef2aSThomas Huth uint64_t address, uint32_t data, PCIDevice *dev) 905fcf5ef2aSThomas Huth { 906b05c81d2SEric Auger AddressSpace *as = pci_device_iommu_address_space(dev); 907b05c81d2SEric Auger hwaddr xlat, len, doorbell_gpa; 908b05c81d2SEric Auger MemoryRegionSection mrs; 909b05c81d2SEric Auger MemoryRegion *mr; 910b05c81d2SEric Auger int ret = 1; 911b05c81d2SEric Auger 912b05c81d2SEric Auger if (as == &address_space_memory) { 913fcf5ef2aSThomas Huth return 0; 914fcf5ef2aSThomas Huth } 915fcf5ef2aSThomas Huth 916b05c81d2SEric Auger /* MSI doorbell address is translated by an IOMMU */ 917b05c81d2SEric Auger 918b05c81d2SEric Auger rcu_read_lock(); 919bc6b1cecSPeter Maydell mr = address_space_translate(as, address, &xlat, &len, true, 920bc6b1cecSPeter Maydell MEMTXATTRS_UNSPECIFIED); 921b05c81d2SEric Auger if (!mr) { 922b05c81d2SEric Auger goto unlock; 923b05c81d2SEric Auger } 924b05c81d2SEric Auger mrs = memory_region_find(mr, xlat, 1); 925b05c81d2SEric Auger if (!mrs.mr) { 926b05c81d2SEric Auger goto unlock; 927b05c81d2SEric Auger } 928b05c81d2SEric Auger 929b05c81d2SEric Auger doorbell_gpa = mrs.offset_within_address_space; 930b05c81d2SEric Auger memory_region_unref(mrs.mr); 931b05c81d2SEric Auger 932b05c81d2SEric Auger route->u.msi.address_lo = doorbell_gpa; 933b05c81d2SEric Auger route->u.msi.address_hi = doorbell_gpa >> 32; 934b05c81d2SEric Auger 935b05c81d2SEric Auger trace_kvm_arm_fixup_msi_route(address, doorbell_gpa); 936b05c81d2SEric Auger 937b05c81d2SEric Auger ret = 0; 938b05c81d2SEric Auger 939b05c81d2SEric Auger unlock: 940b05c81d2SEric Auger rcu_read_unlock(); 941b05c81d2SEric Auger return ret; 942b05c81d2SEric Auger } 943b05c81d2SEric Auger 944fcf5ef2aSThomas Huth int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 945fcf5ef2aSThomas Huth int vector, PCIDevice *dev) 946fcf5ef2aSThomas Huth { 947fcf5ef2aSThomas Huth return 0; 948fcf5ef2aSThomas Huth } 949fcf5ef2aSThomas Huth 950fcf5ef2aSThomas Huth int kvm_arch_release_virq_post(int virq) 951fcf5ef2aSThomas Huth { 952fcf5ef2aSThomas Huth return 0; 953fcf5ef2aSThomas Huth } 954fcf5ef2aSThomas Huth 955fcf5ef2aSThomas Huth int kvm_arch_msi_data_to_gsi(uint32_t data) 956fcf5ef2aSThomas Huth { 957fcf5ef2aSThomas Huth return (data - 32) & 0xffff; 958fcf5ef2aSThomas Huth } 959