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/timer.h" 17fcf5ef2aSThomas Huth #include "qemu/error-report.h" 18db725815SMarkus Armbruster #include "qemu/main-loop.h" 19dea101a1SAndrew Jones #include "qom/object.h" 20dea101a1SAndrew Jones #include "qapi/error.h" 21fcf5ef2aSThomas Huth #include "sysemu/sysemu.h" 22fcf5ef2aSThomas Huth #include "sysemu/kvm.h" 23a27382e2SEric Auger #include "sysemu/kvm_int.h" 24fcf5ef2aSThomas Huth #include "kvm_arm.h" 25fcf5ef2aSThomas Huth #include "cpu.h" 26b05c81d2SEric Auger #include "trace.h" 27fcf5ef2aSThomas Huth #include "internals.h" 28b05c81d2SEric Auger #include "hw/pci/pci.h" 29fcf5ef2aSThomas Huth #include "exec/memattrs.h" 30fcf5ef2aSThomas Huth #include "exec/address-spaces.h" 31fcf5ef2aSThomas Huth #include "hw/boards.h" 3264552b6bSMarkus Armbruster #include "hw/irq.h" 33c8f2eb5dSShameer Kolothum #include "qapi/visitor.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; 42694bcaa8SBeata Michalska static bool cap_has_inject_ext_dabt; 43fcf5ef2aSThomas Huth 44dc40d45eSRichard Henderson /** 45dc40d45eSRichard Henderson * ARMHostCPUFeatures: information about the host CPU (identified 46dc40d45eSRichard Henderson * by asking the host kernel) 47dc40d45eSRichard Henderson */ 48dc40d45eSRichard Henderson typedef struct ARMHostCPUFeatures { 49dc40d45eSRichard Henderson ARMISARegisters isar; 50dc40d45eSRichard Henderson uint64_t features; 51dc40d45eSRichard Henderson uint32_t target; 52dc40d45eSRichard Henderson const char *dtb_compatible; 53dc40d45eSRichard Henderson } ARMHostCPUFeatures; 54dc40d45eSRichard Henderson 55c4487d76SPeter Maydell static ARMHostCPUFeatures arm_host_cpu_features; 56c4487d76SPeter Maydell 57fcf5ef2aSThomas Huth int kvm_arm_vcpu_init(CPUState *cs) 58fcf5ef2aSThomas Huth { 59fcf5ef2aSThomas Huth ARMCPU *cpu = ARM_CPU(cs); 60fcf5ef2aSThomas Huth struct kvm_vcpu_init init; 61fcf5ef2aSThomas Huth 62fcf5ef2aSThomas Huth init.target = cpu->kvm_target; 63fcf5ef2aSThomas Huth memcpy(init.features, cpu->kvm_init_features, sizeof(init.features)); 64fcf5ef2aSThomas Huth 65fcf5ef2aSThomas Huth return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init); 66fcf5ef2aSThomas Huth } 67fcf5ef2aSThomas Huth 6814e99e0fSAndrew Jones int kvm_arm_vcpu_finalize(CPUState *cs, int feature) 6914e99e0fSAndrew Jones { 7014e99e0fSAndrew Jones return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_FINALIZE, &feature); 7114e99e0fSAndrew Jones } 7214e99e0fSAndrew Jones 73202ccb6bSDongjiu Geng void kvm_arm_init_serror_injection(CPUState *cs) 74202ccb6bSDongjiu Geng { 75202ccb6bSDongjiu Geng cap_has_inject_serror_esr = kvm_check_extension(cs->kvm_state, 76202ccb6bSDongjiu Geng KVM_CAP_ARM_INJECT_SERROR_ESR); 77202ccb6bSDongjiu Geng } 78202ccb6bSDongjiu Geng 79fcf5ef2aSThomas Huth bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try, 80fcf5ef2aSThomas Huth int *fdarray, 81fcf5ef2aSThomas Huth struct kvm_vcpu_init *init) 82fcf5ef2aSThomas Huth { 830cdb4020SAndrew Jones int ret = 0, kvmfd = -1, vmfd = -1, cpufd = -1; 84d26f2f93SMarc Zyngier int max_vm_pa_size; 85fcf5ef2aSThomas Huth 86448058aaSDaniel P. Berrangé kvmfd = qemu_open_old("/dev/kvm", O_RDWR); 87fcf5ef2aSThomas Huth if (kvmfd < 0) { 88fcf5ef2aSThomas Huth goto err; 89fcf5ef2aSThomas Huth } 90d26f2f93SMarc Zyngier max_vm_pa_size = ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_ARM_VM_IPA_SIZE); 91d26f2f93SMarc Zyngier if (max_vm_pa_size < 0) { 92d26f2f93SMarc Zyngier max_vm_pa_size = 0; 93d26f2f93SMarc Zyngier } 94bbde13cdSPeter Maydell do { 95d26f2f93SMarc Zyngier vmfd = ioctl(kvmfd, KVM_CREATE_VM, max_vm_pa_size); 96bbde13cdSPeter Maydell } while (vmfd == -1 && errno == EINTR); 97fcf5ef2aSThomas Huth if (vmfd < 0) { 98fcf5ef2aSThomas Huth goto err; 99fcf5ef2aSThomas Huth } 100fcf5ef2aSThomas Huth cpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0); 101fcf5ef2aSThomas Huth if (cpufd < 0) { 102fcf5ef2aSThomas Huth goto err; 103fcf5ef2aSThomas Huth } 104fcf5ef2aSThomas Huth 105fcf5ef2aSThomas Huth if (!init) { 106fcf5ef2aSThomas Huth /* Caller doesn't want the VCPU to be initialized, so skip it */ 107fcf5ef2aSThomas Huth goto finish; 108fcf5ef2aSThomas Huth } 109fcf5ef2aSThomas Huth 1100cdb4020SAndrew Jones if (init->target == -1) { 1110cdb4020SAndrew Jones struct kvm_vcpu_init preferred; 1120cdb4020SAndrew Jones 1130cdb4020SAndrew Jones ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, &preferred); 1140cdb4020SAndrew Jones if (!ret) { 1150cdb4020SAndrew Jones init->target = preferred.target; 1160cdb4020SAndrew Jones } 1170cdb4020SAndrew Jones } 118fcf5ef2aSThomas Huth if (ret >= 0) { 119fcf5ef2aSThomas Huth ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, init); 120fcf5ef2aSThomas Huth if (ret < 0) { 121fcf5ef2aSThomas Huth goto err; 122fcf5ef2aSThomas Huth } 123fcf5ef2aSThomas Huth } else if (cpus_to_try) { 124fcf5ef2aSThomas Huth /* Old kernel which doesn't know about the 125fcf5ef2aSThomas Huth * PREFERRED_TARGET ioctl: we know it will only support 126fcf5ef2aSThomas Huth * creating one kind of guest CPU which is its preferred 127fcf5ef2aSThomas Huth * CPU type. 128fcf5ef2aSThomas Huth */ 1290cdb4020SAndrew Jones struct kvm_vcpu_init try; 1300cdb4020SAndrew Jones 131fcf5ef2aSThomas Huth while (*cpus_to_try != QEMU_KVM_ARM_TARGET_NONE) { 1320cdb4020SAndrew Jones try.target = *cpus_to_try++; 1330cdb4020SAndrew Jones memcpy(try.features, init->features, sizeof(init->features)); 1340cdb4020SAndrew Jones ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, &try); 135fcf5ef2aSThomas Huth if (ret >= 0) { 136fcf5ef2aSThomas Huth break; 137fcf5ef2aSThomas Huth } 138fcf5ef2aSThomas Huth } 139fcf5ef2aSThomas Huth if (ret < 0) { 140fcf5ef2aSThomas Huth goto err; 141fcf5ef2aSThomas Huth } 1420cdb4020SAndrew Jones init->target = try.target; 143fcf5ef2aSThomas Huth } else { 144fcf5ef2aSThomas Huth /* Treat a NULL cpus_to_try argument the same as an empty 145fcf5ef2aSThomas Huth * list, which means we will fail the call since this must 146fcf5ef2aSThomas Huth * be an old kernel which doesn't support PREFERRED_TARGET. 147fcf5ef2aSThomas Huth */ 148fcf5ef2aSThomas Huth goto err; 149fcf5ef2aSThomas Huth } 150fcf5ef2aSThomas Huth 151fcf5ef2aSThomas Huth finish: 152fcf5ef2aSThomas Huth fdarray[0] = kvmfd; 153fcf5ef2aSThomas Huth fdarray[1] = vmfd; 154fcf5ef2aSThomas Huth fdarray[2] = cpufd; 155fcf5ef2aSThomas Huth 156fcf5ef2aSThomas Huth return true; 157fcf5ef2aSThomas Huth 158fcf5ef2aSThomas Huth err: 159fcf5ef2aSThomas Huth if (cpufd >= 0) { 160fcf5ef2aSThomas Huth close(cpufd); 161fcf5ef2aSThomas Huth } 162fcf5ef2aSThomas Huth if (vmfd >= 0) { 163fcf5ef2aSThomas Huth close(vmfd); 164fcf5ef2aSThomas Huth } 165fcf5ef2aSThomas Huth if (kvmfd >= 0) { 166fcf5ef2aSThomas Huth close(kvmfd); 167fcf5ef2aSThomas Huth } 168fcf5ef2aSThomas Huth 169fcf5ef2aSThomas Huth return false; 170fcf5ef2aSThomas Huth } 171fcf5ef2aSThomas Huth 172fcf5ef2aSThomas Huth void kvm_arm_destroy_scratch_host_vcpu(int *fdarray) 173fcf5ef2aSThomas Huth { 174fcf5ef2aSThomas Huth int i; 175fcf5ef2aSThomas Huth 176fcf5ef2aSThomas Huth for (i = 2; i >= 0; i--) { 177fcf5ef2aSThomas Huth close(fdarray[i]); 178fcf5ef2aSThomas Huth } 179fcf5ef2aSThomas Huth } 180fcf5ef2aSThomas Huth 181dc40d45eSRichard Henderson static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) 182dc40d45eSRichard Henderson { 183dc40d45eSRichard Henderson uint64_t ret; 184dc40d45eSRichard Henderson struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)&ret }; 185dc40d45eSRichard Henderson int err; 186dc40d45eSRichard Henderson 187dc40d45eSRichard Henderson assert((id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64); 188dc40d45eSRichard Henderson err = ioctl(fd, KVM_GET_ONE_REG, &idreg); 189dc40d45eSRichard Henderson if (err < 0) { 190dc40d45eSRichard Henderson return -1; 191dc40d45eSRichard Henderson } 192dc40d45eSRichard Henderson *pret = ret; 193dc40d45eSRichard Henderson return 0; 194dc40d45eSRichard Henderson } 195dc40d45eSRichard Henderson 196dc40d45eSRichard Henderson static int read_sys_reg64(int fd, uint64_t *pret, uint64_t id) 197dc40d45eSRichard Henderson { 198dc40d45eSRichard Henderson struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)pret }; 199dc40d45eSRichard Henderson 200dc40d45eSRichard Henderson assert((id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64); 201dc40d45eSRichard Henderson return ioctl(fd, KVM_GET_ONE_REG, &idreg); 202dc40d45eSRichard Henderson } 203dc40d45eSRichard Henderson 204dc40d45eSRichard Henderson static bool kvm_arm_pauth_supported(void) 205dc40d45eSRichard Henderson { 206dc40d45eSRichard Henderson return (kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_ADDRESS) && 207dc40d45eSRichard Henderson kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_GENERIC)); 208dc40d45eSRichard Henderson } 209dc40d45eSRichard Henderson 210dc40d45eSRichard Henderson static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) 211dc40d45eSRichard Henderson { 212dc40d45eSRichard Henderson /* Identify the feature bits corresponding to the host CPU, and 213dc40d45eSRichard Henderson * fill out the ARMHostCPUClass fields accordingly. To do this 214dc40d45eSRichard Henderson * we have to create a scratch VM, create a single CPU inside it, 215dc40d45eSRichard Henderson * and then query that CPU for the relevant ID registers. 216dc40d45eSRichard Henderson */ 217dc40d45eSRichard Henderson int fdarray[3]; 218dc40d45eSRichard Henderson bool sve_supported; 219dc40d45eSRichard Henderson bool pmu_supported = false; 220dc40d45eSRichard Henderson uint64_t features = 0; 221dc40d45eSRichard Henderson int err; 222dc40d45eSRichard Henderson 223dc40d45eSRichard Henderson /* Old kernels may not know about the PREFERRED_TARGET ioctl: however 224dc40d45eSRichard Henderson * we know these will only support creating one kind of guest CPU, 225dc40d45eSRichard Henderson * which is its preferred CPU type. Fortunately these old kernels 226dc40d45eSRichard Henderson * support only a very limited number of CPUs. 227dc40d45eSRichard Henderson */ 228dc40d45eSRichard Henderson static const uint32_t cpus_to_try[] = { 229dc40d45eSRichard Henderson KVM_ARM_TARGET_AEM_V8, 230dc40d45eSRichard Henderson KVM_ARM_TARGET_FOUNDATION_V8, 231dc40d45eSRichard Henderson KVM_ARM_TARGET_CORTEX_A57, 232dc40d45eSRichard Henderson QEMU_KVM_ARM_TARGET_NONE 233dc40d45eSRichard Henderson }; 234dc40d45eSRichard Henderson /* 235dc40d45eSRichard Henderson * target = -1 informs kvm_arm_create_scratch_host_vcpu() 236dc40d45eSRichard Henderson * to use the preferred target 237dc40d45eSRichard Henderson */ 238dc40d45eSRichard Henderson struct kvm_vcpu_init init = { .target = -1, }; 239dc40d45eSRichard Henderson 240dc40d45eSRichard Henderson /* 241dc40d45eSRichard Henderson * Ask for SVE if supported, so that we can query ID_AA64ZFR0, 242dc40d45eSRichard Henderson * which is otherwise RAZ. 243dc40d45eSRichard Henderson */ 244dc40d45eSRichard Henderson sve_supported = kvm_arm_sve_supported(); 245dc40d45eSRichard Henderson if (sve_supported) { 246dc40d45eSRichard Henderson init.features[0] |= 1 << KVM_ARM_VCPU_SVE; 247dc40d45eSRichard Henderson } 248dc40d45eSRichard Henderson 249dc40d45eSRichard Henderson /* 250dc40d45eSRichard Henderson * Ask for Pointer Authentication if supported, so that we get 251dc40d45eSRichard Henderson * the unsanitized field values for AA64ISAR1_EL1. 252dc40d45eSRichard Henderson */ 253dc40d45eSRichard Henderson if (kvm_arm_pauth_supported()) { 254dc40d45eSRichard Henderson init.features[0] |= (1 << KVM_ARM_VCPU_PTRAUTH_ADDRESS | 255dc40d45eSRichard Henderson 1 << KVM_ARM_VCPU_PTRAUTH_GENERIC); 256dc40d45eSRichard Henderson } 257dc40d45eSRichard Henderson 258dc40d45eSRichard Henderson if (kvm_arm_pmu_supported()) { 259dc40d45eSRichard Henderson init.features[0] |= 1 << KVM_ARM_VCPU_PMU_V3; 260dc40d45eSRichard Henderson pmu_supported = true; 261dc40d45eSRichard Henderson } 262dc40d45eSRichard Henderson 263dc40d45eSRichard Henderson if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) { 264dc40d45eSRichard Henderson return false; 265dc40d45eSRichard Henderson } 266dc40d45eSRichard Henderson 267dc40d45eSRichard Henderson ahcf->target = init.target; 268dc40d45eSRichard Henderson ahcf->dtb_compatible = "arm,arm-v8"; 269dc40d45eSRichard Henderson 270dc40d45eSRichard Henderson err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0, 271dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 4, 0)); 272dc40d45eSRichard Henderson if (unlikely(err < 0)) { 273dc40d45eSRichard Henderson /* 274dc40d45eSRichard Henderson * Before v4.15, the kernel only exposed a limited number of system 275dc40d45eSRichard Henderson * registers, not including any of the interesting AArch64 ID regs. 276dc40d45eSRichard Henderson * For the most part we could leave these fields as zero with minimal 277dc40d45eSRichard Henderson * effect, since this does not affect the values seen by the guest. 278dc40d45eSRichard Henderson * 279dc40d45eSRichard Henderson * However, it could cause problems down the line for QEMU, 280dc40d45eSRichard Henderson * so provide a minimal v8.0 default. 281dc40d45eSRichard Henderson * 282dc40d45eSRichard Henderson * ??? Could read MIDR and use knowledge from cpu64.c. 283dc40d45eSRichard Henderson * ??? Could map a page of memory into our temp guest and 284dc40d45eSRichard Henderson * run the tiniest of hand-crafted kernels to extract 285dc40d45eSRichard Henderson * the values seen by the guest. 286dc40d45eSRichard Henderson * ??? Either of these sounds like too much effort just 287dc40d45eSRichard Henderson * to work around running a modern host kernel. 288dc40d45eSRichard Henderson */ 289dc40d45eSRichard Henderson ahcf->isar.id_aa64pfr0 = 0x00000011; /* EL1&0, AArch64 only */ 290dc40d45eSRichard Henderson err = 0; 291dc40d45eSRichard Henderson } else { 292dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1, 293dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 4, 1)); 294dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64smfr0, 295dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 4, 5)); 296dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0, 297dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 5, 0)); 298dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1, 299dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 5, 1)); 300dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0, 301dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 6, 0)); 302dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1, 303dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 6, 1)); 304dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar2, 305dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 6, 2)); 306dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0, 307dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 7, 0)); 308dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1, 309dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 7, 1)); 310dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2, 311dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 7, 2)); 312dc40d45eSRichard Henderson 313dc40d45eSRichard Henderson /* 314dc40d45eSRichard Henderson * Note that if AArch32 support is not present in the host, 315dc40d45eSRichard Henderson * the AArch32 sysregs are present to be read, but will 316dc40d45eSRichard Henderson * return UNKNOWN values. This is neither better nor worse 317dc40d45eSRichard Henderson * than skipping the reads and leaving 0, as we must avoid 318dc40d45eSRichard Henderson * considering the values in every case. 319dc40d45eSRichard Henderson */ 320dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr0, 321dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 0)); 322dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1, 323dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 1)); 324dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, 325dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 2)); 326dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, 327dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 4)); 328dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1, 329dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 5)); 330dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2, 331dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 6)); 332dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3, 333dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 7)); 334dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0, 335dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 0)); 336dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1, 337dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 1)); 338dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2, 339dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 2)); 340dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3, 341dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 3)); 342dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4, 343dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 4)); 344dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5, 345dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 5)); 346dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4, 347dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 6)); 348dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6, 349dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 7)); 350dc40d45eSRichard Henderson 351dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0, 352dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 3, 0)); 353dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1, 354dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 3, 1)); 355dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2, 356dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 3, 2)); 357dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2, 358dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 3, 4)); 359dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr1, 360dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 3, 5)); 361dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr5, 362dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 3, 6)); 363dc40d45eSRichard Henderson 364dc40d45eSRichard Henderson /* 365dc40d45eSRichard Henderson * DBGDIDR is a bit complicated because the kernel doesn't 366dc40d45eSRichard Henderson * provide an accessor for it in 64-bit mode, which is what this 367dc40d45eSRichard Henderson * scratch VM is in, and there's no architected "64-bit sysreg 368dc40d45eSRichard Henderson * which reads the same as the 32-bit register" the way there is 369dc40d45eSRichard Henderson * for other ID registers. Instead we synthesize a value from the 370dc40d45eSRichard Henderson * AArch64 ID_AA64DFR0, the same way the kernel code in 371dc40d45eSRichard Henderson * arch/arm64/kvm/sys_regs.c:trap_dbgidr() does. 372dc40d45eSRichard Henderson * We only do this if the CPU supports AArch32 at EL1. 373dc40d45eSRichard Henderson */ 374dc40d45eSRichard Henderson if (FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL1) >= 2) { 375dc40d45eSRichard Henderson int wrps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, WRPS); 376dc40d45eSRichard Henderson int brps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, BRPS); 377dc40d45eSRichard Henderson int ctx_cmps = 378dc40d45eSRichard Henderson FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS); 379dc40d45eSRichard Henderson int version = 6; /* ARMv8 debug architecture */ 380dc40d45eSRichard Henderson bool has_el3 = 381dc40d45eSRichard Henderson !!FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL3); 382dc40d45eSRichard Henderson uint32_t dbgdidr = 0; 383dc40d45eSRichard Henderson 384dc40d45eSRichard Henderson dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps); 385dc40d45eSRichard Henderson dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, BRPS, brps); 386dc40d45eSRichard Henderson dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, CTX_CMPS, ctx_cmps); 387dc40d45eSRichard Henderson dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, VERSION, version); 388dc40d45eSRichard Henderson dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, NSUHD_IMP, has_el3); 389dc40d45eSRichard Henderson dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, SE_IMP, has_el3); 390dc40d45eSRichard Henderson dbgdidr |= (1 << 15); /* RES1 bit */ 391dc40d45eSRichard Henderson ahcf->isar.dbgdidr = dbgdidr; 392dc40d45eSRichard Henderson } 393dc40d45eSRichard Henderson 394dc40d45eSRichard Henderson if (pmu_supported) { 395dc40d45eSRichard Henderson /* PMCR_EL0 is only accessible if the vCPU has feature PMU_V3 */ 396dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.reset_pmcr_el0, 397dc40d45eSRichard Henderson ARM64_SYS_REG(3, 3, 9, 12, 0)); 398dc40d45eSRichard Henderson } 399dc40d45eSRichard Henderson 400dc40d45eSRichard Henderson if (sve_supported) { 401dc40d45eSRichard Henderson /* 402dc40d45eSRichard Henderson * There is a range of kernels between kernel commit 73433762fcae 403dc40d45eSRichard Henderson * and f81cb2c3ad41 which have a bug where the kernel doesn't 404dc40d45eSRichard Henderson * expose SYS_ID_AA64ZFR0_EL1 via the ONE_REG API unless the VM has 405dc40d45eSRichard Henderson * enabled SVE support, which resulted in an error rather than RAZ. 406dc40d45eSRichard Henderson * So only read the register if we set KVM_ARM_VCPU_SVE above. 407dc40d45eSRichard Henderson */ 408dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0, 409dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 4, 4)); 410dc40d45eSRichard Henderson } 411dc40d45eSRichard Henderson } 412dc40d45eSRichard Henderson 413dc40d45eSRichard Henderson kvm_arm_destroy_scratch_host_vcpu(fdarray); 414dc40d45eSRichard Henderson 415dc40d45eSRichard Henderson if (err < 0) { 416dc40d45eSRichard Henderson return false; 417dc40d45eSRichard Henderson } 418dc40d45eSRichard Henderson 419dc40d45eSRichard Henderson /* 420dc40d45eSRichard Henderson * We can assume any KVM supporting CPU is at least a v8 421dc40d45eSRichard Henderson * with VFPv4+Neon; this in turn implies most of the other 422dc40d45eSRichard Henderson * feature bits. 423dc40d45eSRichard Henderson */ 424dc40d45eSRichard Henderson features |= 1ULL << ARM_FEATURE_V8; 425dc40d45eSRichard Henderson features |= 1ULL << ARM_FEATURE_NEON; 426dc40d45eSRichard Henderson features |= 1ULL << ARM_FEATURE_AARCH64; 427dc40d45eSRichard Henderson features |= 1ULL << ARM_FEATURE_PMU; 428dc40d45eSRichard Henderson features |= 1ULL << ARM_FEATURE_GENERIC_TIMER; 429dc40d45eSRichard Henderson 430dc40d45eSRichard Henderson ahcf->features = features; 431dc40d45eSRichard Henderson 432dc40d45eSRichard Henderson return true; 433dc40d45eSRichard Henderson } 434dc40d45eSRichard Henderson 435c4487d76SPeter Maydell void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) 436fcf5ef2aSThomas Huth { 437c4487d76SPeter Maydell CPUARMState *env = &cpu->env; 438fcf5ef2aSThomas Huth 439c4487d76SPeter Maydell if (!arm_host_cpu_features.dtb_compatible) { 440c4487d76SPeter Maydell if (!kvm_enabled() || 441c4487d76SPeter Maydell !kvm_arm_get_host_cpu_features(&arm_host_cpu_features)) { 442c4487d76SPeter Maydell /* We can't report this error yet, so flag that we need to 443c4487d76SPeter Maydell * in arm_cpu_realizefn(). 444fcf5ef2aSThomas Huth */ 445c4487d76SPeter Maydell cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE; 446c4487d76SPeter Maydell cpu->host_cpu_probe_failed = true; 447c4487d76SPeter Maydell return; 448fcf5ef2aSThomas Huth } 449fcf5ef2aSThomas Huth } 450fcf5ef2aSThomas Huth 451c4487d76SPeter Maydell cpu->kvm_target = arm_host_cpu_features.target; 452c4487d76SPeter Maydell cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible; 4534674097cSRichard Henderson cpu->isar = arm_host_cpu_features.isar; 454c4487d76SPeter Maydell env->features = arm_host_cpu_features.features; 455c4487d76SPeter Maydell } 456c4487d76SPeter Maydell 457dea101a1SAndrew Jones static bool kvm_no_adjvtime_get(Object *obj, Error **errp) 458dea101a1SAndrew Jones { 459dea101a1SAndrew Jones return !ARM_CPU(obj)->kvm_adjvtime; 460dea101a1SAndrew Jones } 461dea101a1SAndrew Jones 462dea101a1SAndrew Jones static void kvm_no_adjvtime_set(Object *obj, bool value, Error **errp) 463dea101a1SAndrew Jones { 464dea101a1SAndrew Jones ARM_CPU(obj)->kvm_adjvtime = !value; 465dea101a1SAndrew Jones } 466dea101a1SAndrew Jones 46768970d1eSAndrew Jones static bool kvm_steal_time_get(Object *obj, Error **errp) 46868970d1eSAndrew Jones { 46968970d1eSAndrew Jones return ARM_CPU(obj)->kvm_steal_time != ON_OFF_AUTO_OFF; 47068970d1eSAndrew Jones } 47168970d1eSAndrew Jones 47268970d1eSAndrew Jones static void kvm_steal_time_set(Object *obj, bool value, Error **errp) 47368970d1eSAndrew Jones { 47468970d1eSAndrew Jones ARM_CPU(obj)->kvm_steal_time = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF; 47568970d1eSAndrew Jones } 47668970d1eSAndrew Jones 477dea101a1SAndrew Jones /* KVM VCPU properties should be prefixed with "kvm-". */ 478dea101a1SAndrew Jones void kvm_arm_add_vcpu_properties(Object *obj) 479dea101a1SAndrew Jones { 4809e6f8d8aSfangying ARMCPU *cpu = ARM_CPU(obj); 4819e6f8d8aSfangying CPUARMState *env = &cpu->env; 482dea101a1SAndrew Jones 4839e6f8d8aSfangying if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) { 4849e6f8d8aSfangying cpu->kvm_adjvtime = true; 485dea101a1SAndrew Jones object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get, 486d2623129SMarkus Armbruster kvm_no_adjvtime_set); 487dea101a1SAndrew Jones object_property_set_description(obj, "kvm-no-adjvtime", 488dea101a1SAndrew Jones "Set on to disable the adjustment of " 489dea101a1SAndrew Jones "the virtual counter. VM stopped time " 4907eecec7dSMarkus Armbruster "will be counted."); 491dea101a1SAndrew Jones } 49268970d1eSAndrew Jones 49368970d1eSAndrew Jones cpu->kvm_steal_time = ON_OFF_AUTO_AUTO; 49468970d1eSAndrew Jones object_property_add_bool(obj, "kvm-steal-time", kvm_steal_time_get, 49568970d1eSAndrew Jones kvm_steal_time_set); 49668970d1eSAndrew Jones object_property_set_description(obj, "kvm-steal-time", 49768970d1eSAndrew Jones "Set off to disable KVM steal time."); 4989e6f8d8aSfangying } 499dea101a1SAndrew Jones 5007d20e681SPhilippe Mathieu-Daudé bool kvm_arm_pmu_supported(void) 501ae502508SAndrew Jones { 5027d20e681SPhilippe Mathieu-Daudé return kvm_check_extension(kvm_state, KVM_CAP_ARM_PMU_V3); 503ae502508SAndrew Jones } 504ae502508SAndrew Jones 505bcb902a1SAndrew Jones int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa) 506a27382e2SEric Auger { 507a27382e2SEric Auger KVMState *s = KVM_STATE(ms->accelerator); 508a27382e2SEric Auger int ret; 509a27382e2SEric Auger 510a27382e2SEric Auger ret = kvm_check_extension(s, KVM_CAP_ARM_VM_IPA_SIZE); 511bcb902a1SAndrew Jones *fixed_ipa = ret <= 0; 512bcb902a1SAndrew Jones 513a27382e2SEric Auger return ret > 0 ? ret : 40; 514a27382e2SEric Auger } 515a27382e2SEric Auger 5165e0d6590SAkihiko Odaki int kvm_arch_get_default_type(MachineState *ms) 5175e0d6590SAkihiko Odaki { 5181ab445afSAkihiko Odaki bool fixed_ipa; 5191ab445afSAkihiko Odaki int size = kvm_arm_get_max_vm_ipa_size(ms, &fixed_ipa); 5201ab445afSAkihiko Odaki return fixed_ipa ? 0 : size; 5215e0d6590SAkihiko Odaki } 5225e0d6590SAkihiko Odaki 523fcf5ef2aSThomas Huth int kvm_arch_init(MachineState *ms, KVMState *s) 524fcf5ef2aSThomas Huth { 525fff9f555SEric Auger int ret = 0; 526fcf5ef2aSThomas Huth /* For ARM interrupt delivery is always asynchronous, 527fcf5ef2aSThomas Huth * whether we are using an in-kernel VGIC or not. 528fcf5ef2aSThomas Huth */ 529fcf5ef2aSThomas Huth kvm_async_interrupts_allowed = true; 530fcf5ef2aSThomas Huth 5315d721b78SAlexander Graf /* 5325d721b78SAlexander Graf * PSCI wakes up secondary cores, so we always need to 5335d721b78SAlexander Graf * have vCPUs waiting in kernel space 5345d721b78SAlexander Graf */ 5355d721b78SAlexander Graf kvm_halt_in_kernel_allowed = true; 5365d721b78SAlexander Graf 537fcf5ef2aSThomas Huth cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); 538fcf5ef2aSThomas Huth 539fff9f555SEric Auger if (ms->smp.cpus > 256 && 540fff9f555SEric Auger !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) { 541fff9f555SEric Auger error_report("Using more than 256 vcpus requires a host kernel " 542fff9f555SEric Auger "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2"); 543fff9f555SEric Auger ret = -EINVAL; 544fff9f555SEric Auger } 545fff9f555SEric Auger 546694bcaa8SBeata Michalska if (kvm_check_extension(s, KVM_CAP_ARM_NISV_TO_USER)) { 547694bcaa8SBeata Michalska if (kvm_vm_enable_cap(s, KVM_CAP_ARM_NISV_TO_USER, 0)) { 548694bcaa8SBeata Michalska error_report("Failed to enable KVM_CAP_ARM_NISV_TO_USER cap"); 549694bcaa8SBeata Michalska } else { 550694bcaa8SBeata Michalska /* Set status for supporting the external dabt injection */ 551694bcaa8SBeata Michalska cap_has_inject_ext_dabt = kvm_check_extension(s, 552694bcaa8SBeata Michalska KVM_CAP_ARM_INJECT_EXT_DABT); 553694bcaa8SBeata Michalska } 554694bcaa8SBeata Michalska } 555694bcaa8SBeata Michalska 556c8f2eb5dSShameer Kolothum if (s->kvm_eager_split_size) { 557c8f2eb5dSShameer Kolothum uint32_t sizes; 558c8f2eb5dSShameer Kolothum 559c8f2eb5dSShameer Kolothum sizes = kvm_vm_check_extension(s, KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES); 560c8f2eb5dSShameer Kolothum if (!sizes) { 561c8f2eb5dSShameer Kolothum s->kvm_eager_split_size = 0; 562c8f2eb5dSShameer Kolothum warn_report("Eager Page Split support not available"); 563c8f2eb5dSShameer Kolothum } else if (!(s->kvm_eager_split_size & sizes)) { 564c8f2eb5dSShameer Kolothum error_report("Eager Page Split requested chunk size not valid"); 565c8f2eb5dSShameer Kolothum ret = -EINVAL; 566c8f2eb5dSShameer Kolothum } else { 567c8f2eb5dSShameer Kolothum ret = kvm_vm_enable_cap(s, KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE, 0, 568c8f2eb5dSShameer Kolothum s->kvm_eager_split_size); 569c8f2eb5dSShameer Kolothum if (ret < 0) { 570c8f2eb5dSShameer Kolothum error_report("Enabling of Eager Page Split failed: %s", 571c8f2eb5dSShameer Kolothum strerror(-ret)); 572c8f2eb5dSShameer Kolothum } 573c8f2eb5dSShameer Kolothum } 574c8f2eb5dSShameer Kolothum } 575c8f2eb5dSShameer Kolothum 576dd2157d2SRichard Henderson max_hw_wps = kvm_check_extension(s, KVM_CAP_GUEST_DEBUG_HW_WPS); 577dd2157d2SRichard Henderson hw_watchpoints = g_array_sized_new(true, true, 578dd2157d2SRichard Henderson sizeof(HWWatchpoint), max_hw_wps); 579dd2157d2SRichard Henderson 580dd2157d2SRichard Henderson max_hw_bps = kvm_check_extension(s, KVM_CAP_GUEST_DEBUG_HW_BPS); 581dd2157d2SRichard Henderson hw_breakpoints = g_array_sized_new(true, true, 582dd2157d2SRichard Henderson sizeof(HWBreakpoint), max_hw_bps); 583ad5c6ddeSAkihiko Odaki 584fff9f555SEric Auger return ret; 585fcf5ef2aSThomas Huth } 586fcf5ef2aSThomas Huth 587fcf5ef2aSThomas Huth unsigned long kvm_arch_vcpu_id(CPUState *cpu) 588fcf5ef2aSThomas Huth { 589fcf5ef2aSThomas Huth return cpu->cpu_index; 590fcf5ef2aSThomas Huth } 591fcf5ef2aSThomas Huth 592fcf5ef2aSThomas Huth /* We track all the KVM devices which need their memory addresses 593fcf5ef2aSThomas Huth * passing to the kernel in a list of these structures. 594fcf5ef2aSThomas Huth * When board init is complete we run through the list and 595fcf5ef2aSThomas Huth * tell the kernel the base addresses of the memory regions. 596fcf5ef2aSThomas Huth * We use a MemoryListener to track mapping and unmapping of 597fcf5ef2aSThomas Huth * the regions during board creation, so the board models don't 598fcf5ef2aSThomas Huth * need to do anything special for the KVM case. 59919d1bd0bSEric Auger * 60019d1bd0bSEric Auger * Sometimes the address must be OR'ed with some other fields 60119d1bd0bSEric Auger * (for example for KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION). 60219d1bd0bSEric Auger * @kda_addr_ormask aims at storing the value of those fields. 603fcf5ef2aSThomas Huth */ 604fcf5ef2aSThomas Huth typedef struct KVMDevice { 605fcf5ef2aSThomas Huth struct kvm_arm_device_addr kda; 606fcf5ef2aSThomas Huth struct kvm_device_attr kdattr; 60719d1bd0bSEric Auger uint64_t kda_addr_ormask; 608fcf5ef2aSThomas Huth MemoryRegion *mr; 609fcf5ef2aSThomas Huth QSLIST_ENTRY(KVMDevice) entries; 610fcf5ef2aSThomas Huth int dev_fd; 611fcf5ef2aSThomas Huth } KVMDevice; 612fcf5ef2aSThomas Huth 613b58deb34SPaolo Bonzini static QSLIST_HEAD(, KVMDevice) kvm_devices_head; 614fcf5ef2aSThomas Huth 615fcf5ef2aSThomas Huth static void kvm_arm_devlistener_add(MemoryListener *listener, 616fcf5ef2aSThomas Huth MemoryRegionSection *section) 617fcf5ef2aSThomas Huth { 618fcf5ef2aSThomas Huth KVMDevice *kd; 619fcf5ef2aSThomas Huth 620fcf5ef2aSThomas Huth QSLIST_FOREACH(kd, &kvm_devices_head, entries) { 621fcf5ef2aSThomas Huth if (section->mr == kd->mr) { 622fcf5ef2aSThomas Huth kd->kda.addr = section->offset_within_address_space; 623fcf5ef2aSThomas Huth } 624fcf5ef2aSThomas Huth } 625fcf5ef2aSThomas Huth } 626fcf5ef2aSThomas Huth 627fcf5ef2aSThomas Huth static void kvm_arm_devlistener_del(MemoryListener *listener, 628fcf5ef2aSThomas Huth MemoryRegionSection *section) 629fcf5ef2aSThomas Huth { 630fcf5ef2aSThomas Huth KVMDevice *kd; 631fcf5ef2aSThomas Huth 632fcf5ef2aSThomas Huth QSLIST_FOREACH(kd, &kvm_devices_head, entries) { 633fcf5ef2aSThomas Huth if (section->mr == kd->mr) { 634fcf5ef2aSThomas Huth kd->kda.addr = -1; 635fcf5ef2aSThomas Huth } 636fcf5ef2aSThomas Huth } 637fcf5ef2aSThomas Huth } 638fcf5ef2aSThomas Huth 639fcf5ef2aSThomas Huth static MemoryListener devlistener = { 640142518bdSPeter Xu .name = "kvm-arm", 641fcf5ef2aSThomas Huth .region_add = kvm_arm_devlistener_add, 642fcf5ef2aSThomas Huth .region_del = kvm_arm_devlistener_del, 64314a868c6SIsaku Yamahata .priority = MEMORY_LISTENER_PRIORITY_MIN, 644fcf5ef2aSThomas Huth }; 645fcf5ef2aSThomas Huth 646fcf5ef2aSThomas Huth static void kvm_arm_set_device_addr(KVMDevice *kd) 647fcf5ef2aSThomas Huth { 648fcf5ef2aSThomas Huth struct kvm_device_attr *attr = &kd->kdattr; 649fcf5ef2aSThomas Huth int ret; 650fcf5ef2aSThomas Huth 651fcf5ef2aSThomas Huth /* If the device control API is available and we have a device fd on the 652fcf5ef2aSThomas Huth * KVMDevice struct, let's use the newer API 653fcf5ef2aSThomas Huth */ 654fcf5ef2aSThomas Huth if (kd->dev_fd >= 0) { 655fcf5ef2aSThomas Huth uint64_t addr = kd->kda.addr; 65619d1bd0bSEric Auger 65719d1bd0bSEric Auger addr |= kd->kda_addr_ormask; 658fcf5ef2aSThomas Huth attr->addr = (uintptr_t)&addr; 659fcf5ef2aSThomas Huth ret = kvm_device_ioctl(kd->dev_fd, KVM_SET_DEVICE_ATTR, attr); 660fcf5ef2aSThomas Huth } else { 661fcf5ef2aSThomas Huth ret = kvm_vm_ioctl(kvm_state, KVM_ARM_SET_DEVICE_ADDR, &kd->kda); 662fcf5ef2aSThomas Huth } 663fcf5ef2aSThomas Huth 664fcf5ef2aSThomas Huth if (ret < 0) { 665fcf5ef2aSThomas Huth fprintf(stderr, "Failed to set device address: %s\n", 666fcf5ef2aSThomas Huth strerror(-ret)); 667fcf5ef2aSThomas Huth abort(); 668fcf5ef2aSThomas Huth } 669fcf5ef2aSThomas Huth } 670fcf5ef2aSThomas Huth 671fcf5ef2aSThomas Huth static void kvm_arm_machine_init_done(Notifier *notifier, void *data) 672fcf5ef2aSThomas Huth { 673fcf5ef2aSThomas Huth KVMDevice *kd, *tkd; 674fcf5ef2aSThomas Huth 675fcf5ef2aSThomas Huth QSLIST_FOREACH_SAFE(kd, &kvm_devices_head, entries, tkd) { 676fcf5ef2aSThomas Huth if (kd->kda.addr != -1) { 677fcf5ef2aSThomas Huth kvm_arm_set_device_addr(kd); 678fcf5ef2aSThomas Huth } 679fcf5ef2aSThomas Huth memory_region_unref(kd->mr); 6805ff9aaabSZheng Xiang QSLIST_REMOVE_HEAD(&kvm_devices_head, entries); 681fcf5ef2aSThomas Huth g_free(kd); 682fcf5ef2aSThomas Huth } 6830bbe4354SPeter Xu memory_listener_unregister(&devlistener); 684fcf5ef2aSThomas Huth } 685fcf5ef2aSThomas Huth 686fcf5ef2aSThomas Huth static Notifier notify = { 687fcf5ef2aSThomas Huth .notify = kvm_arm_machine_init_done, 688fcf5ef2aSThomas Huth }; 689fcf5ef2aSThomas Huth 690fcf5ef2aSThomas Huth void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, 69119d1bd0bSEric Auger uint64_t attr, int dev_fd, uint64_t addr_ormask) 692fcf5ef2aSThomas Huth { 693fcf5ef2aSThomas Huth KVMDevice *kd; 694fcf5ef2aSThomas Huth 695fcf5ef2aSThomas Huth if (!kvm_irqchip_in_kernel()) { 696fcf5ef2aSThomas Huth return; 697fcf5ef2aSThomas Huth } 698fcf5ef2aSThomas Huth 699fcf5ef2aSThomas Huth if (QSLIST_EMPTY(&kvm_devices_head)) { 700fcf5ef2aSThomas Huth memory_listener_register(&devlistener, &address_space_memory); 701fcf5ef2aSThomas Huth qemu_add_machine_init_done_notifier(¬ify); 702fcf5ef2aSThomas Huth } 703fcf5ef2aSThomas Huth kd = g_new0(KVMDevice, 1); 704fcf5ef2aSThomas Huth kd->mr = mr; 705fcf5ef2aSThomas Huth kd->kda.id = devid; 706fcf5ef2aSThomas Huth kd->kda.addr = -1; 707fcf5ef2aSThomas Huth kd->kdattr.flags = 0; 708fcf5ef2aSThomas Huth kd->kdattr.group = group; 709fcf5ef2aSThomas Huth kd->kdattr.attr = attr; 710fcf5ef2aSThomas Huth kd->dev_fd = dev_fd; 71119d1bd0bSEric Auger kd->kda_addr_ormask = addr_ormask; 712fcf5ef2aSThomas Huth QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries); 713fcf5ef2aSThomas Huth memory_region_ref(kd->mr); 714fcf5ef2aSThomas Huth } 715fcf5ef2aSThomas Huth 716fcf5ef2aSThomas Huth static int compare_u64(const void *a, const void *b) 717fcf5ef2aSThomas Huth { 718fcf5ef2aSThomas Huth if (*(uint64_t *)a > *(uint64_t *)b) { 719fcf5ef2aSThomas Huth return 1; 720fcf5ef2aSThomas Huth } 721fcf5ef2aSThomas Huth if (*(uint64_t *)a < *(uint64_t *)b) { 722fcf5ef2aSThomas Huth return -1; 723fcf5ef2aSThomas Huth } 724fcf5ef2aSThomas Huth return 0; 725fcf5ef2aSThomas Huth } 726fcf5ef2aSThomas Huth 727e5ac4200SAndrew Jones /* 728e5ac4200SAndrew Jones * cpreg_values are sorted in ascending order by KVM register ID 729e5ac4200SAndrew Jones * (see kvm_arm_init_cpreg_list). This allows us to cheaply find 730e5ac4200SAndrew Jones * the storage for a KVM register by ID with a binary search. 731e5ac4200SAndrew Jones */ 732e5ac4200SAndrew Jones static uint64_t *kvm_arm_get_cpreg_ptr(ARMCPU *cpu, uint64_t regidx) 733e5ac4200SAndrew Jones { 734e5ac4200SAndrew Jones uint64_t *res; 735e5ac4200SAndrew Jones 736e5ac4200SAndrew Jones res = bsearch(®idx, cpu->cpreg_indexes, cpu->cpreg_array_len, 737e5ac4200SAndrew Jones sizeof(uint64_t), compare_u64); 738e5ac4200SAndrew Jones assert(res); 739e5ac4200SAndrew Jones 740e5ac4200SAndrew Jones return &cpu->cpreg_values[res - cpu->cpreg_indexes]; 741e5ac4200SAndrew Jones } 742e5ac4200SAndrew Jones 743c8a44709SDongjiu Geng /* Initialize the ARMCPU cpreg list according to the kernel's 744fcf5ef2aSThomas Huth * definition of what CPU registers it knows about (and throw away 745fcf5ef2aSThomas Huth * the previous TCG-created cpreg list). 746fcf5ef2aSThomas Huth */ 747fcf5ef2aSThomas Huth int kvm_arm_init_cpreg_list(ARMCPU *cpu) 748fcf5ef2aSThomas Huth { 749fcf5ef2aSThomas Huth struct kvm_reg_list rl; 750fcf5ef2aSThomas Huth struct kvm_reg_list *rlp; 751fcf5ef2aSThomas Huth int i, ret, arraylen; 752fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 753fcf5ef2aSThomas Huth 754fcf5ef2aSThomas Huth rl.n = 0; 755fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, &rl); 756fcf5ef2aSThomas Huth if (ret != -E2BIG) { 757fcf5ef2aSThomas Huth return ret; 758fcf5ef2aSThomas Huth } 759fcf5ef2aSThomas Huth rlp = g_malloc(sizeof(struct kvm_reg_list) + rl.n * sizeof(uint64_t)); 760fcf5ef2aSThomas Huth rlp->n = rl.n; 761fcf5ef2aSThomas Huth ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, rlp); 762fcf5ef2aSThomas Huth if (ret) { 763fcf5ef2aSThomas Huth goto out; 764fcf5ef2aSThomas Huth } 765fcf5ef2aSThomas Huth /* Sort the list we get back from the kernel, since cpreg_tuples 766fcf5ef2aSThomas Huth * must be in strictly ascending order. 767fcf5ef2aSThomas Huth */ 768fcf5ef2aSThomas Huth qsort(&rlp->reg, rlp->n, sizeof(rlp->reg[0]), compare_u64); 769fcf5ef2aSThomas Huth 770fcf5ef2aSThomas Huth for (i = 0, arraylen = 0; i < rlp->n; i++) { 771fcf5ef2aSThomas Huth if (!kvm_arm_reg_syncs_via_cpreg_list(rlp->reg[i])) { 772fcf5ef2aSThomas Huth continue; 773fcf5ef2aSThomas Huth } 774fcf5ef2aSThomas Huth switch (rlp->reg[i] & KVM_REG_SIZE_MASK) { 775fcf5ef2aSThomas Huth case KVM_REG_SIZE_U32: 776fcf5ef2aSThomas Huth case KVM_REG_SIZE_U64: 777fcf5ef2aSThomas Huth break; 778fcf5ef2aSThomas Huth default: 779fcf5ef2aSThomas Huth fprintf(stderr, "Can't handle size of register in kernel list\n"); 780fcf5ef2aSThomas Huth ret = -EINVAL; 781fcf5ef2aSThomas Huth goto out; 782fcf5ef2aSThomas Huth } 783fcf5ef2aSThomas Huth 784fcf5ef2aSThomas Huth arraylen++; 785fcf5ef2aSThomas Huth } 786fcf5ef2aSThomas Huth 787fcf5ef2aSThomas Huth cpu->cpreg_indexes = g_renew(uint64_t, cpu->cpreg_indexes, arraylen); 788fcf5ef2aSThomas Huth cpu->cpreg_values = g_renew(uint64_t, cpu->cpreg_values, arraylen); 789fcf5ef2aSThomas Huth cpu->cpreg_vmstate_indexes = g_renew(uint64_t, cpu->cpreg_vmstate_indexes, 790fcf5ef2aSThomas Huth arraylen); 791fcf5ef2aSThomas Huth cpu->cpreg_vmstate_values = g_renew(uint64_t, cpu->cpreg_vmstate_values, 792fcf5ef2aSThomas Huth arraylen); 793fcf5ef2aSThomas Huth cpu->cpreg_array_len = arraylen; 794fcf5ef2aSThomas Huth cpu->cpreg_vmstate_array_len = arraylen; 795fcf5ef2aSThomas Huth 796fcf5ef2aSThomas Huth for (i = 0, arraylen = 0; i < rlp->n; i++) { 797fcf5ef2aSThomas Huth uint64_t regidx = rlp->reg[i]; 798fcf5ef2aSThomas Huth if (!kvm_arm_reg_syncs_via_cpreg_list(regidx)) { 799fcf5ef2aSThomas Huth continue; 800fcf5ef2aSThomas Huth } 801fcf5ef2aSThomas Huth cpu->cpreg_indexes[arraylen] = regidx; 802fcf5ef2aSThomas Huth arraylen++; 803fcf5ef2aSThomas Huth } 804fcf5ef2aSThomas Huth assert(cpu->cpreg_array_len == arraylen); 805fcf5ef2aSThomas Huth 806fcf5ef2aSThomas Huth if (!write_kvmstate_to_list(cpu)) { 807fcf5ef2aSThomas Huth /* Shouldn't happen unless kernel is inconsistent about 808fcf5ef2aSThomas Huth * what registers exist. 809fcf5ef2aSThomas Huth */ 810fcf5ef2aSThomas Huth fprintf(stderr, "Initial read of kernel register state failed\n"); 811fcf5ef2aSThomas Huth ret = -EINVAL; 812fcf5ef2aSThomas Huth goto out; 813fcf5ef2aSThomas Huth } 814fcf5ef2aSThomas Huth 815fcf5ef2aSThomas Huth out: 816fcf5ef2aSThomas Huth g_free(rlp); 817fcf5ef2aSThomas Huth return ret; 818fcf5ef2aSThomas Huth } 819fcf5ef2aSThomas Huth 820*676fe684SRichard Henderson /** 821*676fe684SRichard Henderson * kvm_arm_cpreg_level: 822*676fe684SRichard Henderson * @regidx: KVM register index 823*676fe684SRichard Henderson * 824*676fe684SRichard Henderson * Return the level of this coprocessor/system register. Return value is 825*676fe684SRichard Henderson * either KVM_PUT_RUNTIME_STATE, KVM_PUT_RESET_STATE, or KVM_PUT_FULL_STATE. 826*676fe684SRichard Henderson */ 827*676fe684SRichard Henderson static int kvm_arm_cpreg_level(uint64_t regidx) 828*676fe684SRichard Henderson { 829*676fe684SRichard Henderson /* 830*676fe684SRichard Henderson * All system registers are assumed to be level KVM_PUT_RUNTIME_STATE. 831*676fe684SRichard Henderson * If a register should be written less often, you must add it here 832*676fe684SRichard Henderson * with a state of either KVM_PUT_RESET_STATE or KVM_PUT_FULL_STATE. 833*676fe684SRichard Henderson */ 834*676fe684SRichard Henderson switch (regidx) { 835*676fe684SRichard Henderson case KVM_REG_ARM_TIMER_CNT: 836*676fe684SRichard Henderson case KVM_REG_ARM_PTIMER_CNT: 837*676fe684SRichard Henderson return KVM_PUT_FULL_STATE; 838*676fe684SRichard Henderson } 839*676fe684SRichard Henderson return KVM_PUT_RUNTIME_STATE; 840*676fe684SRichard Henderson } 841*676fe684SRichard Henderson 842fcf5ef2aSThomas Huth bool write_kvmstate_to_list(ARMCPU *cpu) 843fcf5ef2aSThomas Huth { 844fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 845fcf5ef2aSThomas Huth int i; 846fcf5ef2aSThomas Huth bool ok = true; 847fcf5ef2aSThomas Huth 848fcf5ef2aSThomas Huth for (i = 0; i < cpu->cpreg_array_len; i++) { 849fcf5ef2aSThomas Huth uint64_t regidx = cpu->cpreg_indexes[i]; 850fcf5ef2aSThomas Huth uint32_t v32; 851fcf5ef2aSThomas Huth int ret; 852fcf5ef2aSThomas Huth 853fcf5ef2aSThomas Huth switch (regidx & KVM_REG_SIZE_MASK) { 854fcf5ef2aSThomas Huth case KVM_REG_SIZE_U32: 85540d45b85SCornelia Huck ret = kvm_get_one_reg(cs, regidx, &v32); 856fcf5ef2aSThomas Huth if (!ret) { 857fcf5ef2aSThomas Huth cpu->cpreg_values[i] = v32; 858fcf5ef2aSThomas Huth } 859fcf5ef2aSThomas Huth break; 860fcf5ef2aSThomas Huth case KVM_REG_SIZE_U64: 86140d45b85SCornelia Huck ret = kvm_get_one_reg(cs, regidx, cpu->cpreg_values + i); 862fcf5ef2aSThomas Huth break; 863fcf5ef2aSThomas Huth default: 864d385a605SRichard Henderson g_assert_not_reached(); 865fcf5ef2aSThomas Huth } 866fcf5ef2aSThomas Huth if (ret) { 867fcf5ef2aSThomas Huth ok = false; 868fcf5ef2aSThomas Huth } 869fcf5ef2aSThomas Huth } 870fcf5ef2aSThomas Huth return ok; 871fcf5ef2aSThomas Huth } 872fcf5ef2aSThomas Huth 873fcf5ef2aSThomas Huth bool write_list_to_kvmstate(ARMCPU *cpu, int level) 874fcf5ef2aSThomas Huth { 875fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 876fcf5ef2aSThomas Huth int i; 877fcf5ef2aSThomas Huth bool ok = true; 878fcf5ef2aSThomas Huth 879fcf5ef2aSThomas Huth for (i = 0; i < cpu->cpreg_array_len; i++) { 880fcf5ef2aSThomas Huth uint64_t regidx = cpu->cpreg_indexes[i]; 881fcf5ef2aSThomas Huth uint32_t v32; 882fcf5ef2aSThomas Huth int ret; 883fcf5ef2aSThomas Huth 884fcf5ef2aSThomas Huth if (kvm_arm_cpreg_level(regidx) > level) { 885fcf5ef2aSThomas Huth continue; 886fcf5ef2aSThomas Huth } 887fcf5ef2aSThomas Huth 888fcf5ef2aSThomas Huth switch (regidx & KVM_REG_SIZE_MASK) { 889fcf5ef2aSThomas Huth case KVM_REG_SIZE_U32: 890fcf5ef2aSThomas Huth v32 = cpu->cpreg_values[i]; 8916c8b9a74SCornelia Huck ret = kvm_set_one_reg(cs, regidx, &v32); 892fcf5ef2aSThomas Huth break; 893fcf5ef2aSThomas Huth case KVM_REG_SIZE_U64: 8946c8b9a74SCornelia Huck ret = kvm_set_one_reg(cs, regidx, cpu->cpreg_values + i); 895fcf5ef2aSThomas Huth break; 896fcf5ef2aSThomas Huth default: 897d385a605SRichard Henderson g_assert_not_reached(); 898fcf5ef2aSThomas Huth } 899fcf5ef2aSThomas Huth if (ret) { 900fcf5ef2aSThomas Huth /* We might fail for "unknown register" and also for 901fcf5ef2aSThomas Huth * "you tried to set a register which is constant with 902fcf5ef2aSThomas Huth * a different value from what it actually contains". 903fcf5ef2aSThomas Huth */ 904fcf5ef2aSThomas Huth ok = false; 905fcf5ef2aSThomas Huth } 906fcf5ef2aSThomas Huth } 907fcf5ef2aSThomas Huth return ok; 908fcf5ef2aSThomas Huth } 909fcf5ef2aSThomas Huth 910e5ac4200SAndrew Jones void kvm_arm_cpu_pre_save(ARMCPU *cpu) 911e5ac4200SAndrew Jones { 912e5ac4200SAndrew Jones /* KVM virtual time adjustment */ 913e5ac4200SAndrew Jones if (cpu->kvm_vtime_dirty) { 914e5ac4200SAndrew Jones *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT) = cpu->kvm_vtime; 915e5ac4200SAndrew Jones } 916e5ac4200SAndrew Jones } 917e5ac4200SAndrew Jones 918e5ac4200SAndrew Jones void kvm_arm_cpu_post_load(ARMCPU *cpu) 919e5ac4200SAndrew Jones { 920e5ac4200SAndrew Jones /* KVM virtual time adjustment */ 921e5ac4200SAndrew Jones if (cpu->kvm_adjvtime) { 922e5ac4200SAndrew Jones cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT); 923e5ac4200SAndrew Jones cpu->kvm_vtime_dirty = true; 924e5ac4200SAndrew Jones } 925e5ac4200SAndrew Jones } 926e5ac4200SAndrew Jones 927fcf5ef2aSThomas Huth void kvm_arm_reset_vcpu(ARMCPU *cpu) 928fcf5ef2aSThomas Huth { 929fcf5ef2aSThomas Huth int ret; 930fcf5ef2aSThomas Huth 931fcf5ef2aSThomas Huth /* Re-init VCPU so that all registers are set to 932fcf5ef2aSThomas Huth * their respective reset values. 933fcf5ef2aSThomas Huth */ 934fcf5ef2aSThomas Huth ret = kvm_arm_vcpu_init(CPU(cpu)); 935fcf5ef2aSThomas Huth if (ret < 0) { 936fcf5ef2aSThomas Huth fprintf(stderr, "kvm_arm_vcpu_init failed: %s\n", strerror(-ret)); 937fcf5ef2aSThomas Huth abort(); 938fcf5ef2aSThomas Huth } 939fcf5ef2aSThomas Huth if (!write_kvmstate_to_list(cpu)) { 940fcf5ef2aSThomas Huth fprintf(stderr, "write_kvmstate_to_list failed\n"); 941fcf5ef2aSThomas Huth abort(); 942fcf5ef2aSThomas Huth } 943b698e4eeSPeter Maydell /* 944b698e4eeSPeter Maydell * Sync the reset values also into the CPUState. This is necessary 945b698e4eeSPeter Maydell * because the next thing we do will be a kvm_arch_put_registers() 946b698e4eeSPeter Maydell * which will update the list values from the CPUState before copying 947b698e4eeSPeter Maydell * the list values back to KVM. It's OK to ignore failure returns here 948b698e4eeSPeter Maydell * for the same reason we do so in kvm_arch_get_registers(). 949b698e4eeSPeter Maydell */ 950b698e4eeSPeter Maydell write_list_to_cpustate(cpu); 951fcf5ef2aSThomas Huth } 952fcf5ef2aSThomas Huth 953fcf5ef2aSThomas Huth /* 954fcf5ef2aSThomas Huth * Update KVM's MP_STATE based on what QEMU thinks it is 955fcf5ef2aSThomas Huth */ 956fcf5ef2aSThomas Huth int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu) 957fcf5ef2aSThomas Huth { 958fcf5ef2aSThomas Huth if (cap_has_mp_state) { 959fcf5ef2aSThomas Huth struct kvm_mp_state mp_state = { 960062ba099SAlex Bennée .mp_state = (cpu->power_state == PSCI_OFF) ? 961062ba099SAlex Bennée KVM_MP_STATE_STOPPED : KVM_MP_STATE_RUNNABLE 962fcf5ef2aSThomas Huth }; 963fcf5ef2aSThomas Huth int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state); 964fcf5ef2aSThomas Huth if (ret) { 965fcf5ef2aSThomas Huth fprintf(stderr, "%s: failed to set MP_STATE %d/%s\n", 966fcf5ef2aSThomas Huth __func__, ret, strerror(-ret)); 967fcf5ef2aSThomas Huth return -1; 968fcf5ef2aSThomas Huth } 969fcf5ef2aSThomas Huth } 970fcf5ef2aSThomas Huth 971fcf5ef2aSThomas Huth return 0; 972fcf5ef2aSThomas Huth } 973fcf5ef2aSThomas Huth 974fcf5ef2aSThomas Huth /* 975fcf5ef2aSThomas Huth * Sync the KVM MP_STATE into QEMU 976fcf5ef2aSThomas Huth */ 977fcf5ef2aSThomas Huth int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu) 978fcf5ef2aSThomas Huth { 979fcf5ef2aSThomas Huth if (cap_has_mp_state) { 980fcf5ef2aSThomas Huth struct kvm_mp_state mp_state; 981fcf5ef2aSThomas Huth int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MP_STATE, &mp_state); 982fcf5ef2aSThomas Huth if (ret) { 983fcf5ef2aSThomas Huth fprintf(stderr, "%s: failed to get MP_STATE %d/%s\n", 984fcf5ef2aSThomas Huth __func__, ret, strerror(-ret)); 985fcf5ef2aSThomas Huth abort(); 986fcf5ef2aSThomas Huth } 987062ba099SAlex Bennée cpu->power_state = (mp_state.mp_state == KVM_MP_STATE_STOPPED) ? 988062ba099SAlex Bennée PSCI_OFF : PSCI_ON; 989fcf5ef2aSThomas Huth } 990fcf5ef2aSThomas Huth 991fcf5ef2aSThomas Huth return 0; 992fcf5ef2aSThomas Huth } 993fcf5ef2aSThomas Huth 99446512471SRichard Henderson /** 99546512471SRichard Henderson * kvm_arm_get_virtual_time: 99646512471SRichard Henderson * @cs: CPUState 99746512471SRichard Henderson * 99846512471SRichard Henderson * Gets the VCPU's virtual counter and stores it in the KVM CPU state. 99946512471SRichard Henderson */ 100046512471SRichard Henderson static void kvm_arm_get_virtual_time(CPUState *cs) 1001e5ac4200SAndrew Jones { 1002e5ac4200SAndrew Jones ARMCPU *cpu = ARM_CPU(cs); 1003e5ac4200SAndrew Jones int ret; 1004e5ac4200SAndrew Jones 1005e5ac4200SAndrew Jones if (cpu->kvm_vtime_dirty) { 1006e5ac4200SAndrew Jones return; 1007e5ac4200SAndrew Jones } 1008e5ac4200SAndrew Jones 100940d45b85SCornelia Huck ret = kvm_get_one_reg(cs, KVM_REG_ARM_TIMER_CNT, &cpu->kvm_vtime); 1010e5ac4200SAndrew Jones if (ret) { 1011e5ac4200SAndrew Jones error_report("Failed to get KVM_REG_ARM_TIMER_CNT"); 1012e5ac4200SAndrew Jones abort(); 1013e5ac4200SAndrew Jones } 1014e5ac4200SAndrew Jones 1015e5ac4200SAndrew Jones cpu->kvm_vtime_dirty = true; 1016e5ac4200SAndrew Jones } 1017e5ac4200SAndrew Jones 101846512471SRichard Henderson /** 101946512471SRichard Henderson * kvm_arm_put_virtual_time: 102046512471SRichard Henderson * @cs: CPUState 102146512471SRichard Henderson * 102246512471SRichard Henderson * Sets the VCPU's virtual counter to the value stored in the KVM CPU state. 102346512471SRichard Henderson */ 102446512471SRichard Henderson static void kvm_arm_put_virtual_time(CPUState *cs) 1025e5ac4200SAndrew Jones { 1026e5ac4200SAndrew Jones ARMCPU *cpu = ARM_CPU(cs); 1027e5ac4200SAndrew Jones int ret; 1028e5ac4200SAndrew Jones 1029e5ac4200SAndrew Jones if (!cpu->kvm_vtime_dirty) { 1030e5ac4200SAndrew Jones return; 1031e5ac4200SAndrew Jones } 1032e5ac4200SAndrew Jones 10336c8b9a74SCornelia Huck ret = kvm_set_one_reg(cs, KVM_REG_ARM_TIMER_CNT, &cpu->kvm_vtime); 1034e5ac4200SAndrew Jones if (ret) { 1035e5ac4200SAndrew Jones error_report("Failed to set KVM_REG_ARM_TIMER_CNT"); 1036e5ac4200SAndrew Jones abort(); 1037e5ac4200SAndrew Jones } 1038e5ac4200SAndrew Jones 1039e5ac4200SAndrew Jones cpu->kvm_vtime_dirty = false; 1040e5ac4200SAndrew Jones } 1041e5ac4200SAndrew Jones 1042202ccb6bSDongjiu Geng int kvm_put_vcpu_events(ARMCPU *cpu) 1043202ccb6bSDongjiu Geng { 1044202ccb6bSDongjiu Geng CPUARMState *env = &cpu->env; 1045202ccb6bSDongjiu Geng struct kvm_vcpu_events events; 1046202ccb6bSDongjiu Geng int ret; 1047202ccb6bSDongjiu Geng 1048202ccb6bSDongjiu Geng if (!kvm_has_vcpu_events()) { 1049202ccb6bSDongjiu Geng return 0; 1050202ccb6bSDongjiu Geng } 1051202ccb6bSDongjiu Geng 1052202ccb6bSDongjiu Geng memset(&events, 0, sizeof(events)); 1053202ccb6bSDongjiu Geng events.exception.serror_pending = env->serror.pending; 1054202ccb6bSDongjiu Geng 1055202ccb6bSDongjiu Geng /* Inject SError to guest with specified syndrome if host kernel 1056202ccb6bSDongjiu Geng * supports it, otherwise inject SError without syndrome. 1057202ccb6bSDongjiu Geng */ 1058202ccb6bSDongjiu Geng if (cap_has_inject_serror_esr) { 1059202ccb6bSDongjiu Geng events.exception.serror_has_esr = env->serror.has_esr; 1060202ccb6bSDongjiu Geng events.exception.serror_esr = env->serror.esr; 1061202ccb6bSDongjiu Geng } 1062202ccb6bSDongjiu Geng 1063202ccb6bSDongjiu Geng ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_VCPU_EVENTS, &events); 1064202ccb6bSDongjiu Geng if (ret) { 1065202ccb6bSDongjiu Geng error_report("failed to put vcpu events"); 1066202ccb6bSDongjiu Geng } 1067202ccb6bSDongjiu Geng 1068202ccb6bSDongjiu Geng return ret; 1069202ccb6bSDongjiu Geng } 1070202ccb6bSDongjiu Geng 1071202ccb6bSDongjiu Geng int kvm_get_vcpu_events(ARMCPU *cpu) 1072202ccb6bSDongjiu Geng { 1073202ccb6bSDongjiu Geng CPUARMState *env = &cpu->env; 1074202ccb6bSDongjiu Geng struct kvm_vcpu_events events; 1075202ccb6bSDongjiu Geng int ret; 1076202ccb6bSDongjiu Geng 1077202ccb6bSDongjiu Geng if (!kvm_has_vcpu_events()) { 1078202ccb6bSDongjiu Geng return 0; 1079202ccb6bSDongjiu Geng } 1080202ccb6bSDongjiu Geng 1081202ccb6bSDongjiu Geng memset(&events, 0, sizeof(events)); 1082202ccb6bSDongjiu Geng ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_VCPU_EVENTS, &events); 1083202ccb6bSDongjiu Geng if (ret) { 1084202ccb6bSDongjiu Geng error_report("failed to get vcpu events"); 1085202ccb6bSDongjiu Geng return ret; 1086202ccb6bSDongjiu Geng } 1087202ccb6bSDongjiu Geng 1088202ccb6bSDongjiu Geng env->serror.pending = events.exception.serror_pending; 1089202ccb6bSDongjiu Geng env->serror.has_esr = events.exception.serror_has_esr; 1090202ccb6bSDongjiu Geng env->serror.esr = events.exception.serror_esr; 1091202ccb6bSDongjiu Geng 1092202ccb6bSDongjiu Geng return 0; 1093202ccb6bSDongjiu Geng } 1094202ccb6bSDongjiu Geng 109520c83dc9SRichard Henderson #define ARM64_REG_ESR_EL1 ARM64_SYS_REG(3, 0, 5, 2, 0) 109620c83dc9SRichard Henderson #define ARM64_REG_TCR_EL1 ARM64_SYS_REG(3, 0, 2, 0, 2) 109720c83dc9SRichard Henderson 109820c83dc9SRichard Henderson /* 109920c83dc9SRichard Henderson * ESR_EL1 110020c83dc9SRichard Henderson * ISS encoding 110120c83dc9SRichard Henderson * AARCH64: DFSC, bits [5:0] 110220c83dc9SRichard Henderson * AARCH32: 110320c83dc9SRichard Henderson * TTBCR.EAE == 0 110420c83dc9SRichard Henderson * FS[4] - DFSR[10] 110520c83dc9SRichard Henderson * FS[3:0] - DFSR[3:0] 110620c83dc9SRichard Henderson * TTBCR.EAE == 1 110720c83dc9SRichard Henderson * FS, bits [5:0] 110820c83dc9SRichard Henderson */ 110920c83dc9SRichard Henderson #define ESR_DFSC(aarch64, lpae, v) \ 111020c83dc9SRichard Henderson ((aarch64 || (lpae)) ? ((v) & 0x3F) \ 111120c83dc9SRichard Henderson : (((v) >> 6) | ((v) & 0x1F))) 111220c83dc9SRichard Henderson 111320c83dc9SRichard Henderson #define ESR_DFSC_EXTABT(aarch64, lpae) \ 111420c83dc9SRichard Henderson ((aarch64) ? 0x10 : (lpae) ? 0x10 : 0x8) 111520c83dc9SRichard Henderson 111620c83dc9SRichard Henderson /** 111720c83dc9SRichard Henderson * kvm_arm_verify_ext_dabt_pending: 111820c83dc9SRichard Henderson * @cs: CPUState 111920c83dc9SRichard Henderson * 112020c83dc9SRichard Henderson * Verify the fault status code wrt the Ext DABT injection 112120c83dc9SRichard Henderson * 112220c83dc9SRichard Henderson * Returns: true if the fault status code is as expected, false otherwise 112320c83dc9SRichard Henderson */ 112420c83dc9SRichard Henderson static bool kvm_arm_verify_ext_dabt_pending(CPUState *cs) 112520c83dc9SRichard Henderson { 112620c83dc9SRichard Henderson uint64_t dfsr_val; 112720c83dc9SRichard Henderson 112820c83dc9SRichard Henderson if (!kvm_get_one_reg(cs, ARM64_REG_ESR_EL1, &dfsr_val)) { 112920c83dc9SRichard Henderson ARMCPU *cpu = ARM_CPU(cs); 113020c83dc9SRichard Henderson CPUARMState *env = &cpu->env; 113120c83dc9SRichard Henderson int aarch64_mode = arm_feature(env, ARM_FEATURE_AARCH64); 113220c83dc9SRichard Henderson int lpae = 0; 113320c83dc9SRichard Henderson 113420c83dc9SRichard Henderson if (!aarch64_mode) { 113520c83dc9SRichard Henderson uint64_t ttbcr; 113620c83dc9SRichard Henderson 113720c83dc9SRichard Henderson if (!kvm_get_one_reg(cs, ARM64_REG_TCR_EL1, &ttbcr)) { 113820c83dc9SRichard Henderson lpae = arm_feature(env, ARM_FEATURE_LPAE) 113920c83dc9SRichard Henderson && (ttbcr & TTBCR_EAE); 114020c83dc9SRichard Henderson } 114120c83dc9SRichard Henderson } 114220c83dc9SRichard Henderson /* 114320c83dc9SRichard Henderson * The verification here is based on the DFSC bits 114420c83dc9SRichard Henderson * of the ESR_EL1 reg only 114520c83dc9SRichard Henderson */ 114620c83dc9SRichard Henderson return (ESR_DFSC(aarch64_mode, lpae, dfsr_val) == 114720c83dc9SRichard Henderson ESR_DFSC_EXTABT(aarch64_mode, lpae)); 114820c83dc9SRichard Henderson } 114920c83dc9SRichard Henderson return false; 115020c83dc9SRichard Henderson } 115120c83dc9SRichard Henderson 1152fcf5ef2aSThomas Huth void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 1153fcf5ef2aSThomas Huth { 11541711bfa5SBeata Michalska ARMCPU *cpu = ARM_CPU(cs); 11551711bfa5SBeata Michalska CPUARMState *env = &cpu->env; 11561711bfa5SBeata Michalska 11571711bfa5SBeata Michalska if (unlikely(env->ext_dabt_raised)) { 11581711bfa5SBeata Michalska /* 11591711bfa5SBeata Michalska * Verifying that the ext DABT has been properly injected, 11601711bfa5SBeata Michalska * otherwise risking indefinitely re-running the faulting instruction 11611711bfa5SBeata Michalska * Covering a very narrow case for kernels 5.5..5.5.4 11621711bfa5SBeata Michalska * when injected abort was misconfigured to be 11631711bfa5SBeata Michalska * an IMPLEMENTATION DEFINED exception (for 32-bit EL1) 11641711bfa5SBeata Michalska */ 11651711bfa5SBeata Michalska if (!arm_feature(env, ARM_FEATURE_AARCH64) && 11661711bfa5SBeata Michalska unlikely(!kvm_arm_verify_ext_dabt_pending(cs))) { 11671711bfa5SBeata Michalska 11681711bfa5SBeata Michalska error_report("Data abort exception with no valid ISS generated by " 11691711bfa5SBeata Michalska "guest memory access. KVM unable to emulate faulting " 11701711bfa5SBeata Michalska "instruction. Failed to inject an external data abort " 11711711bfa5SBeata Michalska "into the guest."); 11721711bfa5SBeata Michalska abort(); 11731711bfa5SBeata Michalska } 11741711bfa5SBeata Michalska /* Clear the status */ 11751711bfa5SBeata Michalska env->ext_dabt_raised = 0; 11761711bfa5SBeata Michalska } 1177fcf5ef2aSThomas Huth } 1178fcf5ef2aSThomas Huth 1179fcf5ef2aSThomas Huth MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 1180fcf5ef2aSThomas Huth { 11815d721b78SAlexander Graf ARMCPU *cpu; 11825d721b78SAlexander Graf uint32_t switched_level; 11835d721b78SAlexander Graf 11845d721b78SAlexander Graf if (kvm_irqchip_in_kernel()) { 11855d721b78SAlexander Graf /* 11865d721b78SAlexander Graf * We only need to sync timer states with user-space interrupt 11875d721b78SAlexander Graf * controllers, so return early and save cycles if we don't. 11885d721b78SAlexander Graf */ 11895d721b78SAlexander Graf return MEMTXATTRS_UNSPECIFIED; 11905d721b78SAlexander Graf } 11915d721b78SAlexander Graf 11925d721b78SAlexander Graf cpu = ARM_CPU(cs); 11935d721b78SAlexander Graf 11945d721b78SAlexander Graf /* Synchronize our shadowed in-kernel device irq lines with the kvm ones */ 11955d721b78SAlexander Graf if (run->s.regs.device_irq_level != cpu->device_irq_level) { 11965d721b78SAlexander Graf switched_level = cpu->device_irq_level ^ run->s.regs.device_irq_level; 11975d721b78SAlexander Graf 11985d721b78SAlexander Graf qemu_mutex_lock_iothread(); 11995d721b78SAlexander Graf 12005d721b78SAlexander Graf if (switched_level & KVM_ARM_DEV_EL1_VTIMER) { 12015d721b78SAlexander Graf qemu_set_irq(cpu->gt_timer_outputs[GTIMER_VIRT], 12025d721b78SAlexander Graf !!(run->s.regs.device_irq_level & 12035d721b78SAlexander Graf KVM_ARM_DEV_EL1_VTIMER)); 12045d721b78SAlexander Graf switched_level &= ~KVM_ARM_DEV_EL1_VTIMER; 12055d721b78SAlexander Graf } 12065d721b78SAlexander Graf 12075d721b78SAlexander Graf if (switched_level & KVM_ARM_DEV_EL1_PTIMER) { 12085d721b78SAlexander Graf qemu_set_irq(cpu->gt_timer_outputs[GTIMER_PHYS], 12095d721b78SAlexander Graf !!(run->s.regs.device_irq_level & 12105d721b78SAlexander Graf KVM_ARM_DEV_EL1_PTIMER)); 12115d721b78SAlexander Graf switched_level &= ~KVM_ARM_DEV_EL1_PTIMER; 12125d721b78SAlexander Graf } 12135d721b78SAlexander Graf 1214b1659527SAndrew Jones if (switched_level & KVM_ARM_DEV_PMU) { 1215b1659527SAndrew Jones qemu_set_irq(cpu->pmu_interrupt, 1216b1659527SAndrew Jones !!(run->s.regs.device_irq_level & KVM_ARM_DEV_PMU)); 1217b1659527SAndrew Jones switched_level &= ~KVM_ARM_DEV_PMU; 1218b1659527SAndrew Jones } 12195d721b78SAlexander Graf 12205d721b78SAlexander Graf if (switched_level) { 12215d721b78SAlexander Graf qemu_log_mask(LOG_UNIMP, "%s: unhandled in-kernel device IRQ %x\n", 12225d721b78SAlexander Graf __func__, switched_level); 12235d721b78SAlexander Graf } 12245d721b78SAlexander Graf 12255d721b78SAlexander Graf /* We also mark unknown levels as processed to not waste cycles */ 12265d721b78SAlexander Graf cpu->device_irq_level = run->s.regs.device_irq_level; 12275d721b78SAlexander Graf qemu_mutex_unlock_iothread(); 12285d721b78SAlexander Graf } 12295d721b78SAlexander Graf 1230fcf5ef2aSThomas Huth return MEMTXATTRS_UNSPECIFIED; 1231fcf5ef2aSThomas Huth } 1232fcf5ef2aSThomas Huth 1233538f0497SPhilippe Mathieu-Daudé void kvm_arm_vm_state_change(void *opaque, bool running, RunState state) 1234e5ac4200SAndrew Jones { 1235e5ac4200SAndrew Jones CPUState *cs = opaque; 1236e5ac4200SAndrew Jones ARMCPU *cpu = ARM_CPU(cs); 1237e5ac4200SAndrew Jones 1238e5ac4200SAndrew Jones if (running) { 1239e5ac4200SAndrew Jones if (cpu->kvm_adjvtime) { 1240e5ac4200SAndrew Jones kvm_arm_put_virtual_time(cs); 1241e5ac4200SAndrew Jones } 1242e5ac4200SAndrew Jones } else { 1243e5ac4200SAndrew Jones if (cpu->kvm_adjvtime) { 1244e5ac4200SAndrew Jones kvm_arm_get_virtual_time(cs); 1245e5ac4200SAndrew Jones } 1246e5ac4200SAndrew Jones } 1247e5ac4200SAndrew Jones } 1248fcf5ef2aSThomas Huth 1249694bcaa8SBeata Michalska /** 1250694bcaa8SBeata Michalska * kvm_arm_handle_dabt_nisv: 1251694bcaa8SBeata Michalska * @cs: CPUState 1252694bcaa8SBeata Michalska * @esr_iss: ISS encoding (limited) for the exception from Data Abort 1253694bcaa8SBeata Michalska * ISV bit set to '0b0' -> no valid instruction syndrome 1254694bcaa8SBeata Michalska * @fault_ipa: faulting address for the synchronous data abort 1255694bcaa8SBeata Michalska * 1256694bcaa8SBeata Michalska * Returns: 0 if the exception has been handled, < 0 otherwise 1257694bcaa8SBeata Michalska */ 1258694bcaa8SBeata Michalska static int kvm_arm_handle_dabt_nisv(CPUState *cs, uint64_t esr_iss, 1259694bcaa8SBeata Michalska uint64_t fault_ipa) 1260694bcaa8SBeata Michalska { 12611711bfa5SBeata Michalska ARMCPU *cpu = ARM_CPU(cs); 12621711bfa5SBeata Michalska CPUARMState *env = &cpu->env; 1263694bcaa8SBeata Michalska /* 1264694bcaa8SBeata Michalska * Request KVM to inject the external data abort into the guest 1265694bcaa8SBeata Michalska */ 1266694bcaa8SBeata Michalska if (cap_has_inject_ext_dabt) { 1267694bcaa8SBeata Michalska struct kvm_vcpu_events events = { }; 1268694bcaa8SBeata Michalska /* 1269694bcaa8SBeata Michalska * The external data abort event will be handled immediately by KVM 1270694bcaa8SBeata Michalska * using the address fault that triggered the exit on given VCPU. 1271694bcaa8SBeata Michalska * Requesting injection of the external data abort does not rely 1272694bcaa8SBeata Michalska * on any other VCPU state. Therefore, in this particular case, the VCPU 1273694bcaa8SBeata Michalska * synchronization can be exceptionally skipped. 1274694bcaa8SBeata Michalska */ 1275694bcaa8SBeata Michalska events.exception.ext_dabt_pending = 1; 1276694bcaa8SBeata Michalska /* KVM_CAP_ARM_INJECT_EXT_DABT implies KVM_CAP_VCPU_EVENTS */ 12771711bfa5SBeata Michalska if (!kvm_vcpu_ioctl(cs, KVM_SET_VCPU_EVENTS, &events)) { 12781711bfa5SBeata Michalska env->ext_dabt_raised = 1; 12791711bfa5SBeata Michalska return 0; 12801711bfa5SBeata Michalska } 1281694bcaa8SBeata Michalska } else { 1282694bcaa8SBeata Michalska error_report("Data abort exception triggered by guest memory access " 1283694bcaa8SBeata Michalska "at physical address: 0x" TARGET_FMT_lx, 1284694bcaa8SBeata Michalska (target_ulong)fault_ipa); 1285694bcaa8SBeata Michalska error_printf("KVM unable to emulate faulting instruction.\n"); 1286694bcaa8SBeata Michalska } 1287694bcaa8SBeata Michalska return -1; 1288694bcaa8SBeata Michalska } 1289694bcaa8SBeata Michalska 12905cba8f26SRichard Henderson /** 12915cba8f26SRichard Henderson * kvm_arm_handle_debug: 12925cba8f26SRichard Henderson * @cs: CPUState 12935cba8f26SRichard Henderson * @debug_exit: debug part of the KVM exit structure 12945cba8f26SRichard Henderson * 12955cba8f26SRichard Henderson * Returns: TRUE if the debug exception was handled. 12965cba8f26SRichard Henderson * 12975cba8f26SRichard Henderson * See v8 ARM ARM D7.2.27 ESR_ELx, Exception Syndrome Register 12985cba8f26SRichard Henderson * 12995cba8f26SRichard Henderson * To minimise translating between kernel and user-space the kernel 13005cba8f26SRichard Henderson * ABI just provides user-space with the full exception syndrome 13015cba8f26SRichard Henderson * register value to be decoded in QEMU. 13025cba8f26SRichard Henderson */ 13035cba8f26SRichard Henderson static bool kvm_arm_handle_debug(CPUState *cs, 13045cba8f26SRichard Henderson struct kvm_debug_exit_arch *debug_exit) 13055cba8f26SRichard Henderson { 13065cba8f26SRichard Henderson int hsr_ec = syn_get_ec(debug_exit->hsr); 13075cba8f26SRichard Henderson ARMCPU *cpu = ARM_CPU(cs); 13085cba8f26SRichard Henderson CPUARMState *env = &cpu->env; 13095cba8f26SRichard Henderson 13105cba8f26SRichard Henderson /* Ensure PC is synchronised */ 13115cba8f26SRichard Henderson kvm_cpu_synchronize_state(cs); 13125cba8f26SRichard Henderson 13135cba8f26SRichard Henderson switch (hsr_ec) { 13145cba8f26SRichard Henderson case EC_SOFTWARESTEP: 13155cba8f26SRichard Henderson if (cs->singlestep_enabled) { 13165cba8f26SRichard Henderson return true; 13175cba8f26SRichard Henderson } else { 13185cba8f26SRichard Henderson /* 13195cba8f26SRichard Henderson * The kernel should have suppressed the guest's ability to 13205cba8f26SRichard Henderson * single step at this point so something has gone wrong. 13215cba8f26SRichard Henderson */ 13225cba8f26SRichard Henderson error_report("%s: guest single-step while debugging unsupported" 13235cba8f26SRichard Henderson " (%"PRIx64", %"PRIx32")", 13245cba8f26SRichard Henderson __func__, env->pc, debug_exit->hsr); 13255cba8f26SRichard Henderson return false; 13265cba8f26SRichard Henderson } 13275cba8f26SRichard Henderson break; 13285cba8f26SRichard Henderson case EC_AA64_BKPT: 13295cba8f26SRichard Henderson if (kvm_find_sw_breakpoint(cs, env->pc)) { 13305cba8f26SRichard Henderson return true; 13315cba8f26SRichard Henderson } 13325cba8f26SRichard Henderson break; 13335cba8f26SRichard Henderson case EC_BREAKPOINT: 13345cba8f26SRichard Henderson if (find_hw_breakpoint(cs, env->pc)) { 13355cba8f26SRichard Henderson return true; 13365cba8f26SRichard Henderson } 13375cba8f26SRichard Henderson break; 13385cba8f26SRichard Henderson case EC_WATCHPOINT: 13395cba8f26SRichard Henderson { 13405cba8f26SRichard Henderson CPUWatchpoint *wp = find_hw_watchpoint(cs, debug_exit->far); 13415cba8f26SRichard Henderson if (wp) { 13425cba8f26SRichard Henderson cs->watchpoint_hit = wp; 13435cba8f26SRichard Henderson return true; 13445cba8f26SRichard Henderson } 13455cba8f26SRichard Henderson break; 13465cba8f26SRichard Henderson } 13475cba8f26SRichard Henderson default: 13485cba8f26SRichard Henderson error_report("%s: unhandled debug exit (%"PRIx32", %"PRIx64")", 13495cba8f26SRichard Henderson __func__, debug_exit->hsr, env->pc); 13505cba8f26SRichard Henderson } 13515cba8f26SRichard Henderson 13525cba8f26SRichard Henderson /* If we are not handling the debug exception it must belong to 13535cba8f26SRichard Henderson * the guest. Let's re-use the existing TCG interrupt code to set 13545cba8f26SRichard Henderson * everything up properly. 13555cba8f26SRichard Henderson */ 13565cba8f26SRichard Henderson cs->exception_index = EXCP_BKPT; 13575cba8f26SRichard Henderson env->exception.syndrome = debug_exit->hsr; 13585cba8f26SRichard Henderson env->exception.vaddress = debug_exit->far; 13595cba8f26SRichard Henderson env->exception.target_el = 1; 13605cba8f26SRichard Henderson qemu_mutex_lock_iothread(); 13615cba8f26SRichard Henderson arm_cpu_do_interrupt(cs); 13625cba8f26SRichard Henderson qemu_mutex_unlock_iothread(); 13635cba8f26SRichard Henderson 13645cba8f26SRichard Henderson return false; 13655cba8f26SRichard Henderson } 13665cba8f26SRichard Henderson 1367fcf5ef2aSThomas Huth int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 1368fcf5ef2aSThomas Huth { 1369fcf5ef2aSThomas Huth int ret = 0; 1370fcf5ef2aSThomas Huth 1371fcf5ef2aSThomas Huth switch (run->exit_reason) { 1372fcf5ef2aSThomas Huth case KVM_EXIT_DEBUG: 1373fcf5ef2aSThomas Huth if (kvm_arm_handle_debug(cs, &run->debug.arch)) { 1374fcf5ef2aSThomas Huth ret = EXCP_DEBUG; 1375fcf5ef2aSThomas Huth } /* otherwise return to guest */ 1376fcf5ef2aSThomas Huth break; 1377694bcaa8SBeata Michalska case KVM_EXIT_ARM_NISV: 1378694bcaa8SBeata Michalska /* External DABT with no valid iss to decode */ 1379694bcaa8SBeata Michalska ret = kvm_arm_handle_dabt_nisv(cs, run->arm_nisv.esr_iss, 1380694bcaa8SBeata Michalska run->arm_nisv.fault_ipa); 1381694bcaa8SBeata Michalska break; 1382fcf5ef2aSThomas Huth default: 1383fcf5ef2aSThomas Huth qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", 1384fcf5ef2aSThomas Huth __func__, run->exit_reason); 1385fcf5ef2aSThomas Huth break; 1386fcf5ef2aSThomas Huth } 1387fcf5ef2aSThomas Huth return ret; 1388fcf5ef2aSThomas Huth } 1389fcf5ef2aSThomas Huth 1390fcf5ef2aSThomas Huth bool kvm_arch_stop_on_emulation_error(CPUState *cs) 1391fcf5ef2aSThomas Huth { 1392fcf5ef2aSThomas Huth return true; 1393fcf5ef2aSThomas Huth } 1394fcf5ef2aSThomas Huth 1395fcf5ef2aSThomas Huth int kvm_arch_process_async_events(CPUState *cs) 1396fcf5ef2aSThomas Huth { 1397fcf5ef2aSThomas Huth return 0; 1398fcf5ef2aSThomas Huth } 1399fcf5ef2aSThomas Huth 1400ec4145f7SRichard Henderson /** 1401ea79c599SRichard Henderson * kvm_arm_hw_debug_active: 1402ea79c599SRichard Henderson * @cs: CPU State 1403ea79c599SRichard Henderson * 1404ea79c599SRichard Henderson * Return: TRUE if any hardware breakpoints in use. 1405ea79c599SRichard Henderson */ 1406ea79c599SRichard Henderson static bool kvm_arm_hw_debug_active(CPUState *cs) 1407ea79c599SRichard Henderson { 1408ea79c599SRichard Henderson return ((cur_hw_wps > 0) || (cur_hw_bps > 0)); 1409ea79c599SRichard Henderson } 1410ea79c599SRichard Henderson 1411ea79c599SRichard Henderson /** 1412ec4145f7SRichard Henderson * kvm_arm_copy_hw_debug_data: 1413ec4145f7SRichard Henderson * @ptr: kvm_guest_debug_arch structure 1414ec4145f7SRichard Henderson * 1415ec4145f7SRichard Henderson * Copy the architecture specific debug registers into the 1416ec4145f7SRichard Henderson * kvm_guest_debug ioctl structure. 1417ec4145f7SRichard Henderson */ 1418ec4145f7SRichard Henderson static void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr) 1419ec4145f7SRichard Henderson { 1420ec4145f7SRichard Henderson int i; 1421ec4145f7SRichard Henderson memset(ptr, 0, sizeof(struct kvm_guest_debug_arch)); 1422ec4145f7SRichard Henderson 1423ec4145f7SRichard Henderson for (i = 0; i < max_hw_wps; i++) { 1424ec4145f7SRichard Henderson HWWatchpoint *wp = get_hw_wp(i); 1425ec4145f7SRichard Henderson ptr->dbg_wcr[i] = wp->wcr; 1426ec4145f7SRichard Henderson ptr->dbg_wvr[i] = wp->wvr; 1427ec4145f7SRichard Henderson } 1428ec4145f7SRichard Henderson for (i = 0; i < max_hw_bps; i++) { 1429ec4145f7SRichard Henderson HWBreakpoint *bp = get_hw_bp(i); 1430ec4145f7SRichard Henderson ptr->dbg_bcr[i] = bp->bcr; 1431ec4145f7SRichard Henderson ptr->dbg_bvr[i] = bp->bvr; 1432ec4145f7SRichard Henderson } 1433ec4145f7SRichard Henderson } 1434ec4145f7SRichard Henderson 1435fcf5ef2aSThomas Huth void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) 1436fcf5ef2aSThomas Huth { 1437fcf5ef2aSThomas Huth if (kvm_sw_breakpoints_active(cs)) { 1438fcf5ef2aSThomas Huth dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; 1439fcf5ef2aSThomas Huth } 1440fcf5ef2aSThomas Huth if (kvm_arm_hw_debug_active(cs)) { 1441fcf5ef2aSThomas Huth dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW; 1442fcf5ef2aSThomas Huth kvm_arm_copy_hw_debug_data(&dbg->arch); 1443fcf5ef2aSThomas Huth } 1444fcf5ef2aSThomas Huth } 1445fcf5ef2aSThomas Huth 1446fcf5ef2aSThomas Huth void kvm_arch_init_irq_routing(KVMState *s) 1447fcf5ef2aSThomas Huth { 1448fcf5ef2aSThomas Huth } 1449fcf5ef2aSThomas Huth 14504376c40dSPaolo Bonzini int kvm_arch_irqchip_create(KVMState *s) 1451fcf5ef2aSThomas Huth { 14524376c40dSPaolo Bonzini if (kvm_kernel_irqchip_split()) { 145347c182feSCornelia Huck error_report("-machine kernel_irqchip=split is not supported on ARM."); 1454fcf5ef2aSThomas Huth exit(1); 1455fcf5ef2aSThomas Huth } 1456fcf5ef2aSThomas Huth 1457fcf5ef2aSThomas Huth /* If we can create the VGIC using the newer device control API, we 1458fcf5ef2aSThomas Huth * let the device do this when it initializes itself, otherwise we 1459fcf5ef2aSThomas Huth * fall back to the old API */ 1460fcf5ef2aSThomas Huth return kvm_check_extension(s, KVM_CAP_DEVICE_CTRL); 1461fcf5ef2aSThomas Huth } 1462fcf5ef2aSThomas Huth 1463fcf5ef2aSThomas Huth int kvm_arm_vgic_probe(void) 1464fcf5ef2aSThomas Huth { 1465d45efe47SEric Auger int val = 0; 1466d45efe47SEric Auger 1467fcf5ef2aSThomas Huth if (kvm_create_device(kvm_state, 1468fcf5ef2aSThomas Huth KVM_DEV_TYPE_ARM_VGIC_V3, true) == 0) { 1469d45efe47SEric Auger val |= KVM_ARM_VGIC_V3; 1470fcf5ef2aSThomas Huth } 1471d45efe47SEric Auger if (kvm_create_device(kvm_state, 1472d45efe47SEric Auger KVM_DEV_TYPE_ARM_VGIC_V2, true) == 0) { 1473d45efe47SEric Auger val |= KVM_ARM_VGIC_V2; 1474d45efe47SEric Auger } 1475d45efe47SEric Auger return val; 1476fcf5ef2aSThomas Huth } 1477fcf5ef2aSThomas Huth 1478f6530926SEric Auger int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level) 1479f6530926SEric Auger { 1480f6530926SEric Auger int kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT) | irq; 1481f6530926SEric Auger int cpu_idx1 = cpu % 256; 1482f6530926SEric Auger int cpu_idx2 = cpu / 256; 1483f6530926SEric Auger 1484f6530926SEric Auger kvm_irq |= (cpu_idx1 << KVM_ARM_IRQ_VCPU_SHIFT) | 1485f6530926SEric Auger (cpu_idx2 << KVM_ARM_IRQ_VCPU2_SHIFT); 1486f6530926SEric Auger 1487f6530926SEric Auger return kvm_set_irq(kvm_state, kvm_irq, !!level); 1488f6530926SEric Auger } 1489f6530926SEric Auger 1490fcf5ef2aSThomas Huth int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 1491fcf5ef2aSThomas Huth uint64_t address, uint32_t data, PCIDevice *dev) 1492fcf5ef2aSThomas Huth { 1493b05c81d2SEric Auger AddressSpace *as = pci_device_iommu_address_space(dev); 1494b05c81d2SEric Auger hwaddr xlat, len, doorbell_gpa; 1495b05c81d2SEric Auger MemoryRegionSection mrs; 1496b05c81d2SEric Auger MemoryRegion *mr; 1497b05c81d2SEric Auger 1498b05c81d2SEric Auger if (as == &address_space_memory) { 1499fcf5ef2aSThomas Huth return 0; 1500fcf5ef2aSThomas Huth } 1501fcf5ef2aSThomas Huth 1502b05c81d2SEric Auger /* MSI doorbell address is translated by an IOMMU */ 1503b05c81d2SEric Auger 1504dfa0d9b8SHamza Mahfooz RCU_READ_LOCK_GUARD(); 1505dfa0d9b8SHamza Mahfooz 1506bc6b1cecSPeter Maydell mr = address_space_translate(as, address, &xlat, &len, true, 1507bc6b1cecSPeter Maydell MEMTXATTRS_UNSPECIFIED); 1508dfa0d9b8SHamza Mahfooz 1509b05c81d2SEric Auger if (!mr) { 1510dfa0d9b8SHamza Mahfooz return 1; 1511b05c81d2SEric Auger } 1512dfa0d9b8SHamza Mahfooz 1513b05c81d2SEric Auger mrs = memory_region_find(mr, xlat, 1); 1514dfa0d9b8SHamza Mahfooz 1515b05c81d2SEric Auger if (!mrs.mr) { 1516dfa0d9b8SHamza Mahfooz return 1; 1517b05c81d2SEric Auger } 1518b05c81d2SEric Auger 1519b05c81d2SEric Auger doorbell_gpa = mrs.offset_within_address_space; 1520b05c81d2SEric Auger memory_region_unref(mrs.mr); 1521b05c81d2SEric Auger 1522b05c81d2SEric Auger route->u.msi.address_lo = doorbell_gpa; 1523b05c81d2SEric Auger route->u.msi.address_hi = doorbell_gpa >> 32; 1524b05c81d2SEric Auger 1525b05c81d2SEric Auger trace_kvm_arm_fixup_msi_route(address, doorbell_gpa); 1526b05c81d2SEric Auger 1527dfa0d9b8SHamza Mahfooz return 0; 1528b05c81d2SEric Auger } 1529b05c81d2SEric Auger 1530fcf5ef2aSThomas Huth int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 1531fcf5ef2aSThomas Huth int vector, PCIDevice *dev) 1532fcf5ef2aSThomas Huth { 1533fcf5ef2aSThomas Huth return 0; 1534fcf5ef2aSThomas Huth } 1535fcf5ef2aSThomas Huth 1536fcf5ef2aSThomas Huth int kvm_arch_release_virq_post(int virq) 1537fcf5ef2aSThomas Huth { 1538fcf5ef2aSThomas Huth return 0; 1539fcf5ef2aSThomas Huth } 1540fcf5ef2aSThomas Huth 1541fcf5ef2aSThomas Huth int kvm_arch_msi_data_to_gsi(uint32_t data) 1542fcf5ef2aSThomas Huth { 1543fcf5ef2aSThomas Huth return (data - 32) & 0xffff; 1544fcf5ef2aSThomas Huth } 154592a5199bSTom Lendacky 154692a5199bSTom Lendacky bool kvm_arch_cpu_check_are_resettable(void) 154792a5199bSTom Lendacky { 154892a5199bSTom Lendacky return true; 154992a5199bSTom Lendacky } 15503dba0a33SPaolo Bonzini 1551c8f2eb5dSShameer Kolothum static void kvm_arch_get_eager_split_size(Object *obj, Visitor *v, 1552c8f2eb5dSShameer Kolothum const char *name, void *opaque, 1553c8f2eb5dSShameer Kolothum Error **errp) 1554c8f2eb5dSShameer Kolothum { 1555c8f2eb5dSShameer Kolothum KVMState *s = KVM_STATE(obj); 1556c8f2eb5dSShameer Kolothum uint64_t value = s->kvm_eager_split_size; 1557c8f2eb5dSShameer Kolothum 1558c8f2eb5dSShameer Kolothum visit_type_size(v, name, &value, errp); 1559c8f2eb5dSShameer Kolothum } 1560c8f2eb5dSShameer Kolothum 1561c8f2eb5dSShameer Kolothum static void kvm_arch_set_eager_split_size(Object *obj, Visitor *v, 1562c8f2eb5dSShameer Kolothum const char *name, void *opaque, 1563c8f2eb5dSShameer Kolothum Error **errp) 1564c8f2eb5dSShameer Kolothum { 1565c8f2eb5dSShameer Kolothum KVMState *s = KVM_STATE(obj); 1566c8f2eb5dSShameer Kolothum uint64_t value; 1567c8f2eb5dSShameer Kolothum 1568c8f2eb5dSShameer Kolothum if (s->fd != -1) { 1569c8f2eb5dSShameer Kolothum error_setg(errp, "Unable to set early-split-size after KVM has been initialized"); 1570c8f2eb5dSShameer Kolothum return; 1571c8f2eb5dSShameer Kolothum } 1572c8f2eb5dSShameer Kolothum 1573c8f2eb5dSShameer Kolothum if (!visit_type_size(v, name, &value, errp)) { 1574c8f2eb5dSShameer Kolothum return; 1575c8f2eb5dSShameer Kolothum } 1576c8f2eb5dSShameer Kolothum 1577c8f2eb5dSShameer Kolothum if (value && !is_power_of_2(value)) { 1578c8f2eb5dSShameer Kolothum error_setg(errp, "early-split-size must be a power of two"); 1579c8f2eb5dSShameer Kolothum return; 1580c8f2eb5dSShameer Kolothum } 1581c8f2eb5dSShameer Kolothum 1582c8f2eb5dSShameer Kolothum s->kvm_eager_split_size = value; 1583c8f2eb5dSShameer Kolothum } 1584c8f2eb5dSShameer Kolothum 15853dba0a33SPaolo Bonzini void kvm_arch_accel_class_init(ObjectClass *oc) 15863dba0a33SPaolo Bonzini { 1587c8f2eb5dSShameer Kolothum object_class_property_add(oc, "eager-split-size", "size", 1588c8f2eb5dSShameer Kolothum kvm_arch_get_eager_split_size, 1589c8f2eb5dSShameer Kolothum kvm_arch_set_eager_split_size, NULL, NULL); 1590c8f2eb5dSShameer Kolothum 1591c8f2eb5dSShameer Kolothum object_class_property_set_description(oc, "eager-split-size", 1592c8f2eb5dSShameer Kolothum "Eager Page Split chunk size for hugepages. (default: 0, disabled)"); 15933dba0a33SPaolo Bonzini } 1594