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 44*dc40d45eSRichard Henderson /** 45*dc40d45eSRichard Henderson * ARMHostCPUFeatures: information about the host CPU (identified 46*dc40d45eSRichard Henderson * by asking the host kernel) 47*dc40d45eSRichard Henderson */ 48*dc40d45eSRichard Henderson typedef struct ARMHostCPUFeatures { 49*dc40d45eSRichard Henderson ARMISARegisters isar; 50*dc40d45eSRichard Henderson uint64_t features; 51*dc40d45eSRichard Henderson uint32_t target; 52*dc40d45eSRichard Henderson const char *dtb_compatible; 53*dc40d45eSRichard Henderson } ARMHostCPUFeatures; 54*dc40d45eSRichard 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 181*dc40d45eSRichard Henderson static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) 182*dc40d45eSRichard Henderson { 183*dc40d45eSRichard Henderson uint64_t ret; 184*dc40d45eSRichard Henderson struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)&ret }; 185*dc40d45eSRichard Henderson int err; 186*dc40d45eSRichard Henderson 187*dc40d45eSRichard Henderson assert((id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64); 188*dc40d45eSRichard Henderson err = ioctl(fd, KVM_GET_ONE_REG, &idreg); 189*dc40d45eSRichard Henderson if (err < 0) { 190*dc40d45eSRichard Henderson return -1; 191*dc40d45eSRichard Henderson } 192*dc40d45eSRichard Henderson *pret = ret; 193*dc40d45eSRichard Henderson return 0; 194*dc40d45eSRichard Henderson } 195*dc40d45eSRichard Henderson 196*dc40d45eSRichard Henderson static int read_sys_reg64(int fd, uint64_t *pret, uint64_t id) 197*dc40d45eSRichard Henderson { 198*dc40d45eSRichard Henderson struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)pret }; 199*dc40d45eSRichard Henderson 200*dc40d45eSRichard Henderson assert((id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64); 201*dc40d45eSRichard Henderson return ioctl(fd, KVM_GET_ONE_REG, &idreg); 202*dc40d45eSRichard Henderson } 203*dc40d45eSRichard Henderson 204*dc40d45eSRichard Henderson static bool kvm_arm_pauth_supported(void) 205*dc40d45eSRichard Henderson { 206*dc40d45eSRichard Henderson return (kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_ADDRESS) && 207*dc40d45eSRichard Henderson kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_GENERIC)); 208*dc40d45eSRichard Henderson } 209*dc40d45eSRichard Henderson 210*dc40d45eSRichard Henderson static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) 211*dc40d45eSRichard Henderson { 212*dc40d45eSRichard Henderson /* Identify the feature bits corresponding to the host CPU, and 213*dc40d45eSRichard Henderson * fill out the ARMHostCPUClass fields accordingly. To do this 214*dc40d45eSRichard Henderson * we have to create a scratch VM, create a single CPU inside it, 215*dc40d45eSRichard Henderson * and then query that CPU for the relevant ID registers. 216*dc40d45eSRichard Henderson */ 217*dc40d45eSRichard Henderson int fdarray[3]; 218*dc40d45eSRichard Henderson bool sve_supported; 219*dc40d45eSRichard Henderson bool pmu_supported = false; 220*dc40d45eSRichard Henderson uint64_t features = 0; 221*dc40d45eSRichard Henderson int err; 222*dc40d45eSRichard Henderson 223*dc40d45eSRichard Henderson /* Old kernels may not know about the PREFERRED_TARGET ioctl: however 224*dc40d45eSRichard Henderson * we know these will only support creating one kind of guest CPU, 225*dc40d45eSRichard Henderson * which is its preferred CPU type. Fortunately these old kernels 226*dc40d45eSRichard Henderson * support only a very limited number of CPUs. 227*dc40d45eSRichard Henderson */ 228*dc40d45eSRichard Henderson static const uint32_t cpus_to_try[] = { 229*dc40d45eSRichard Henderson KVM_ARM_TARGET_AEM_V8, 230*dc40d45eSRichard Henderson KVM_ARM_TARGET_FOUNDATION_V8, 231*dc40d45eSRichard Henderson KVM_ARM_TARGET_CORTEX_A57, 232*dc40d45eSRichard Henderson QEMU_KVM_ARM_TARGET_NONE 233*dc40d45eSRichard Henderson }; 234*dc40d45eSRichard Henderson /* 235*dc40d45eSRichard Henderson * target = -1 informs kvm_arm_create_scratch_host_vcpu() 236*dc40d45eSRichard Henderson * to use the preferred target 237*dc40d45eSRichard Henderson */ 238*dc40d45eSRichard Henderson struct kvm_vcpu_init init = { .target = -1, }; 239*dc40d45eSRichard Henderson 240*dc40d45eSRichard Henderson /* 241*dc40d45eSRichard Henderson * Ask for SVE if supported, so that we can query ID_AA64ZFR0, 242*dc40d45eSRichard Henderson * which is otherwise RAZ. 243*dc40d45eSRichard Henderson */ 244*dc40d45eSRichard Henderson sve_supported = kvm_arm_sve_supported(); 245*dc40d45eSRichard Henderson if (sve_supported) { 246*dc40d45eSRichard Henderson init.features[0] |= 1 << KVM_ARM_VCPU_SVE; 247*dc40d45eSRichard Henderson } 248*dc40d45eSRichard Henderson 249*dc40d45eSRichard Henderson /* 250*dc40d45eSRichard Henderson * Ask for Pointer Authentication if supported, so that we get 251*dc40d45eSRichard Henderson * the unsanitized field values for AA64ISAR1_EL1. 252*dc40d45eSRichard Henderson */ 253*dc40d45eSRichard Henderson if (kvm_arm_pauth_supported()) { 254*dc40d45eSRichard Henderson init.features[0] |= (1 << KVM_ARM_VCPU_PTRAUTH_ADDRESS | 255*dc40d45eSRichard Henderson 1 << KVM_ARM_VCPU_PTRAUTH_GENERIC); 256*dc40d45eSRichard Henderson } 257*dc40d45eSRichard Henderson 258*dc40d45eSRichard Henderson if (kvm_arm_pmu_supported()) { 259*dc40d45eSRichard Henderson init.features[0] |= 1 << KVM_ARM_VCPU_PMU_V3; 260*dc40d45eSRichard Henderson pmu_supported = true; 261*dc40d45eSRichard Henderson } 262*dc40d45eSRichard Henderson 263*dc40d45eSRichard Henderson if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) { 264*dc40d45eSRichard Henderson return false; 265*dc40d45eSRichard Henderson } 266*dc40d45eSRichard Henderson 267*dc40d45eSRichard Henderson ahcf->target = init.target; 268*dc40d45eSRichard Henderson ahcf->dtb_compatible = "arm,arm-v8"; 269*dc40d45eSRichard Henderson 270*dc40d45eSRichard Henderson err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0, 271*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 4, 0)); 272*dc40d45eSRichard Henderson if (unlikely(err < 0)) { 273*dc40d45eSRichard Henderson /* 274*dc40d45eSRichard Henderson * Before v4.15, the kernel only exposed a limited number of system 275*dc40d45eSRichard Henderson * registers, not including any of the interesting AArch64 ID regs. 276*dc40d45eSRichard Henderson * For the most part we could leave these fields as zero with minimal 277*dc40d45eSRichard Henderson * effect, since this does not affect the values seen by the guest. 278*dc40d45eSRichard Henderson * 279*dc40d45eSRichard Henderson * However, it could cause problems down the line for QEMU, 280*dc40d45eSRichard Henderson * so provide a minimal v8.0 default. 281*dc40d45eSRichard Henderson * 282*dc40d45eSRichard Henderson * ??? Could read MIDR and use knowledge from cpu64.c. 283*dc40d45eSRichard Henderson * ??? Could map a page of memory into our temp guest and 284*dc40d45eSRichard Henderson * run the tiniest of hand-crafted kernels to extract 285*dc40d45eSRichard Henderson * the values seen by the guest. 286*dc40d45eSRichard Henderson * ??? Either of these sounds like too much effort just 287*dc40d45eSRichard Henderson * to work around running a modern host kernel. 288*dc40d45eSRichard Henderson */ 289*dc40d45eSRichard Henderson ahcf->isar.id_aa64pfr0 = 0x00000011; /* EL1&0, AArch64 only */ 290*dc40d45eSRichard Henderson err = 0; 291*dc40d45eSRichard Henderson } else { 292*dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1, 293*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 4, 1)); 294*dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64smfr0, 295*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 4, 5)); 296*dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0, 297*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 5, 0)); 298*dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1, 299*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 5, 1)); 300*dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0, 301*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 6, 0)); 302*dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1, 303*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 6, 1)); 304*dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar2, 305*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 6, 2)); 306*dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr0, 307*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 7, 0)); 308*dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1, 309*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 7, 1)); 310*dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2, 311*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 7, 2)); 312*dc40d45eSRichard Henderson 313*dc40d45eSRichard Henderson /* 314*dc40d45eSRichard Henderson * Note that if AArch32 support is not present in the host, 315*dc40d45eSRichard Henderson * the AArch32 sysregs are present to be read, but will 316*dc40d45eSRichard Henderson * return UNKNOWN values. This is neither better nor worse 317*dc40d45eSRichard Henderson * than skipping the reads and leaving 0, as we must avoid 318*dc40d45eSRichard Henderson * considering the values in every case. 319*dc40d45eSRichard Henderson */ 320*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr0, 321*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 0)); 322*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1, 323*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 1)); 324*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, 325*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 2)); 326*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, 327*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 4)); 328*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1, 329*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 5)); 330*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2, 331*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 6)); 332*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3, 333*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 1, 7)); 334*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0, 335*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 0)); 336*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1, 337*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 1)); 338*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2, 339*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 2)); 340*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3, 341*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 3)); 342*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4, 343*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 4)); 344*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5, 345*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 5)); 346*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4, 347*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 6)); 348*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6, 349*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 2, 7)); 350*dc40d45eSRichard Henderson 351*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0, 352*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 3, 0)); 353*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1, 354*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 3, 1)); 355*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2, 356*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 3, 2)); 357*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2, 358*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 3, 4)); 359*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr1, 360*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 3, 5)); 361*dc40d45eSRichard Henderson err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr5, 362*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 3, 6)); 363*dc40d45eSRichard Henderson 364*dc40d45eSRichard Henderson /* 365*dc40d45eSRichard Henderson * DBGDIDR is a bit complicated because the kernel doesn't 366*dc40d45eSRichard Henderson * provide an accessor for it in 64-bit mode, which is what this 367*dc40d45eSRichard Henderson * scratch VM is in, and there's no architected "64-bit sysreg 368*dc40d45eSRichard Henderson * which reads the same as the 32-bit register" the way there is 369*dc40d45eSRichard Henderson * for other ID registers. Instead we synthesize a value from the 370*dc40d45eSRichard Henderson * AArch64 ID_AA64DFR0, the same way the kernel code in 371*dc40d45eSRichard Henderson * arch/arm64/kvm/sys_regs.c:trap_dbgidr() does. 372*dc40d45eSRichard Henderson * We only do this if the CPU supports AArch32 at EL1. 373*dc40d45eSRichard Henderson */ 374*dc40d45eSRichard Henderson if (FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL1) >= 2) { 375*dc40d45eSRichard Henderson int wrps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, WRPS); 376*dc40d45eSRichard Henderson int brps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, BRPS); 377*dc40d45eSRichard Henderson int ctx_cmps = 378*dc40d45eSRichard Henderson FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS); 379*dc40d45eSRichard Henderson int version = 6; /* ARMv8 debug architecture */ 380*dc40d45eSRichard Henderson bool has_el3 = 381*dc40d45eSRichard Henderson !!FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL3); 382*dc40d45eSRichard Henderson uint32_t dbgdidr = 0; 383*dc40d45eSRichard Henderson 384*dc40d45eSRichard Henderson dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps); 385*dc40d45eSRichard Henderson dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, BRPS, brps); 386*dc40d45eSRichard Henderson dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, CTX_CMPS, ctx_cmps); 387*dc40d45eSRichard Henderson dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, VERSION, version); 388*dc40d45eSRichard Henderson dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, NSUHD_IMP, has_el3); 389*dc40d45eSRichard Henderson dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, SE_IMP, has_el3); 390*dc40d45eSRichard Henderson dbgdidr |= (1 << 15); /* RES1 bit */ 391*dc40d45eSRichard Henderson ahcf->isar.dbgdidr = dbgdidr; 392*dc40d45eSRichard Henderson } 393*dc40d45eSRichard Henderson 394*dc40d45eSRichard Henderson if (pmu_supported) { 395*dc40d45eSRichard Henderson /* PMCR_EL0 is only accessible if the vCPU has feature PMU_V3 */ 396*dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.reset_pmcr_el0, 397*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 3, 9, 12, 0)); 398*dc40d45eSRichard Henderson } 399*dc40d45eSRichard Henderson 400*dc40d45eSRichard Henderson if (sve_supported) { 401*dc40d45eSRichard Henderson /* 402*dc40d45eSRichard Henderson * There is a range of kernels between kernel commit 73433762fcae 403*dc40d45eSRichard Henderson * and f81cb2c3ad41 which have a bug where the kernel doesn't 404*dc40d45eSRichard Henderson * expose SYS_ID_AA64ZFR0_EL1 via the ONE_REG API unless the VM has 405*dc40d45eSRichard Henderson * enabled SVE support, which resulted in an error rather than RAZ. 406*dc40d45eSRichard Henderson * So only read the register if we set KVM_ARM_VCPU_SVE above. 407*dc40d45eSRichard Henderson */ 408*dc40d45eSRichard Henderson err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0, 409*dc40d45eSRichard Henderson ARM64_SYS_REG(3, 0, 0, 4, 4)); 410*dc40d45eSRichard Henderson } 411*dc40d45eSRichard Henderson } 412*dc40d45eSRichard Henderson 413*dc40d45eSRichard Henderson kvm_arm_destroy_scratch_host_vcpu(fdarray); 414*dc40d45eSRichard Henderson 415*dc40d45eSRichard Henderson if (err < 0) { 416*dc40d45eSRichard Henderson return false; 417*dc40d45eSRichard Henderson } 418*dc40d45eSRichard Henderson 419*dc40d45eSRichard Henderson /* 420*dc40d45eSRichard Henderson * We can assume any KVM supporting CPU is at least a v8 421*dc40d45eSRichard Henderson * with VFPv4+Neon; this in turn implies most of the other 422*dc40d45eSRichard Henderson * feature bits. 423*dc40d45eSRichard Henderson */ 424*dc40d45eSRichard Henderson features |= 1ULL << ARM_FEATURE_V8; 425*dc40d45eSRichard Henderson features |= 1ULL << ARM_FEATURE_NEON; 426*dc40d45eSRichard Henderson features |= 1ULL << ARM_FEATURE_AARCH64; 427*dc40d45eSRichard Henderson features |= 1ULL << ARM_FEATURE_PMU; 428*dc40d45eSRichard Henderson features |= 1ULL << ARM_FEATURE_GENERIC_TIMER; 429*dc40d45eSRichard Henderson 430*dc40d45eSRichard Henderson ahcf->features = features; 431*dc40d45eSRichard Henderson 432*dc40d45eSRichard Henderson return true; 433*dc40d45eSRichard Henderson } 434*dc40d45eSRichard 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 820fcf5ef2aSThomas Huth bool write_kvmstate_to_list(ARMCPU *cpu) 821fcf5ef2aSThomas Huth { 822fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 823fcf5ef2aSThomas Huth int i; 824fcf5ef2aSThomas Huth bool ok = true; 825fcf5ef2aSThomas Huth 826fcf5ef2aSThomas Huth for (i = 0; i < cpu->cpreg_array_len; i++) { 827fcf5ef2aSThomas Huth uint64_t regidx = cpu->cpreg_indexes[i]; 828fcf5ef2aSThomas Huth uint32_t v32; 829fcf5ef2aSThomas Huth int ret; 830fcf5ef2aSThomas Huth 831fcf5ef2aSThomas Huth switch (regidx & KVM_REG_SIZE_MASK) { 832fcf5ef2aSThomas Huth case KVM_REG_SIZE_U32: 83340d45b85SCornelia Huck ret = kvm_get_one_reg(cs, regidx, &v32); 834fcf5ef2aSThomas Huth if (!ret) { 835fcf5ef2aSThomas Huth cpu->cpreg_values[i] = v32; 836fcf5ef2aSThomas Huth } 837fcf5ef2aSThomas Huth break; 838fcf5ef2aSThomas Huth case KVM_REG_SIZE_U64: 83940d45b85SCornelia Huck ret = kvm_get_one_reg(cs, regidx, cpu->cpreg_values + i); 840fcf5ef2aSThomas Huth break; 841fcf5ef2aSThomas Huth default: 842d385a605SRichard Henderson g_assert_not_reached(); 843fcf5ef2aSThomas Huth } 844fcf5ef2aSThomas Huth if (ret) { 845fcf5ef2aSThomas Huth ok = false; 846fcf5ef2aSThomas Huth } 847fcf5ef2aSThomas Huth } 848fcf5ef2aSThomas Huth return ok; 849fcf5ef2aSThomas Huth } 850fcf5ef2aSThomas Huth 851fcf5ef2aSThomas Huth bool write_list_to_kvmstate(ARMCPU *cpu, int level) 852fcf5ef2aSThomas Huth { 853fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 854fcf5ef2aSThomas Huth int i; 855fcf5ef2aSThomas Huth bool ok = true; 856fcf5ef2aSThomas Huth 857fcf5ef2aSThomas Huth for (i = 0; i < cpu->cpreg_array_len; i++) { 858fcf5ef2aSThomas Huth uint64_t regidx = cpu->cpreg_indexes[i]; 859fcf5ef2aSThomas Huth uint32_t v32; 860fcf5ef2aSThomas Huth int ret; 861fcf5ef2aSThomas Huth 862fcf5ef2aSThomas Huth if (kvm_arm_cpreg_level(regidx) > level) { 863fcf5ef2aSThomas Huth continue; 864fcf5ef2aSThomas Huth } 865fcf5ef2aSThomas Huth 866fcf5ef2aSThomas Huth switch (regidx & KVM_REG_SIZE_MASK) { 867fcf5ef2aSThomas Huth case KVM_REG_SIZE_U32: 868fcf5ef2aSThomas Huth v32 = cpu->cpreg_values[i]; 8696c8b9a74SCornelia Huck ret = kvm_set_one_reg(cs, regidx, &v32); 870fcf5ef2aSThomas Huth break; 871fcf5ef2aSThomas Huth case KVM_REG_SIZE_U64: 8726c8b9a74SCornelia Huck ret = kvm_set_one_reg(cs, regidx, cpu->cpreg_values + i); 873fcf5ef2aSThomas Huth break; 874fcf5ef2aSThomas Huth default: 875d385a605SRichard Henderson g_assert_not_reached(); 876fcf5ef2aSThomas Huth } 877fcf5ef2aSThomas Huth if (ret) { 878fcf5ef2aSThomas Huth /* We might fail for "unknown register" and also for 879fcf5ef2aSThomas Huth * "you tried to set a register which is constant with 880fcf5ef2aSThomas Huth * a different value from what it actually contains". 881fcf5ef2aSThomas Huth */ 882fcf5ef2aSThomas Huth ok = false; 883fcf5ef2aSThomas Huth } 884fcf5ef2aSThomas Huth } 885fcf5ef2aSThomas Huth return ok; 886fcf5ef2aSThomas Huth } 887fcf5ef2aSThomas Huth 888e5ac4200SAndrew Jones void kvm_arm_cpu_pre_save(ARMCPU *cpu) 889e5ac4200SAndrew Jones { 890e5ac4200SAndrew Jones /* KVM virtual time adjustment */ 891e5ac4200SAndrew Jones if (cpu->kvm_vtime_dirty) { 892e5ac4200SAndrew Jones *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT) = cpu->kvm_vtime; 893e5ac4200SAndrew Jones } 894e5ac4200SAndrew Jones } 895e5ac4200SAndrew Jones 896e5ac4200SAndrew Jones void kvm_arm_cpu_post_load(ARMCPU *cpu) 897e5ac4200SAndrew Jones { 898e5ac4200SAndrew Jones /* KVM virtual time adjustment */ 899e5ac4200SAndrew Jones if (cpu->kvm_adjvtime) { 900e5ac4200SAndrew Jones cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT); 901e5ac4200SAndrew Jones cpu->kvm_vtime_dirty = true; 902e5ac4200SAndrew Jones } 903e5ac4200SAndrew Jones } 904e5ac4200SAndrew Jones 905fcf5ef2aSThomas Huth void kvm_arm_reset_vcpu(ARMCPU *cpu) 906fcf5ef2aSThomas Huth { 907fcf5ef2aSThomas Huth int ret; 908fcf5ef2aSThomas Huth 909fcf5ef2aSThomas Huth /* Re-init VCPU so that all registers are set to 910fcf5ef2aSThomas Huth * their respective reset values. 911fcf5ef2aSThomas Huth */ 912fcf5ef2aSThomas Huth ret = kvm_arm_vcpu_init(CPU(cpu)); 913fcf5ef2aSThomas Huth if (ret < 0) { 914fcf5ef2aSThomas Huth fprintf(stderr, "kvm_arm_vcpu_init failed: %s\n", strerror(-ret)); 915fcf5ef2aSThomas Huth abort(); 916fcf5ef2aSThomas Huth } 917fcf5ef2aSThomas Huth if (!write_kvmstate_to_list(cpu)) { 918fcf5ef2aSThomas Huth fprintf(stderr, "write_kvmstate_to_list failed\n"); 919fcf5ef2aSThomas Huth abort(); 920fcf5ef2aSThomas Huth } 921b698e4eeSPeter Maydell /* 922b698e4eeSPeter Maydell * Sync the reset values also into the CPUState. This is necessary 923b698e4eeSPeter Maydell * because the next thing we do will be a kvm_arch_put_registers() 924b698e4eeSPeter Maydell * which will update the list values from the CPUState before copying 925b698e4eeSPeter Maydell * the list values back to KVM. It's OK to ignore failure returns here 926b698e4eeSPeter Maydell * for the same reason we do so in kvm_arch_get_registers(). 927b698e4eeSPeter Maydell */ 928b698e4eeSPeter Maydell write_list_to_cpustate(cpu); 929fcf5ef2aSThomas Huth } 930fcf5ef2aSThomas Huth 931fcf5ef2aSThomas Huth /* 932fcf5ef2aSThomas Huth * Update KVM's MP_STATE based on what QEMU thinks it is 933fcf5ef2aSThomas Huth */ 934fcf5ef2aSThomas Huth int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu) 935fcf5ef2aSThomas Huth { 936fcf5ef2aSThomas Huth if (cap_has_mp_state) { 937fcf5ef2aSThomas Huth struct kvm_mp_state mp_state = { 938062ba099SAlex Bennée .mp_state = (cpu->power_state == PSCI_OFF) ? 939062ba099SAlex Bennée KVM_MP_STATE_STOPPED : KVM_MP_STATE_RUNNABLE 940fcf5ef2aSThomas Huth }; 941fcf5ef2aSThomas Huth int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state); 942fcf5ef2aSThomas Huth if (ret) { 943fcf5ef2aSThomas Huth fprintf(stderr, "%s: failed to set MP_STATE %d/%s\n", 944fcf5ef2aSThomas Huth __func__, ret, strerror(-ret)); 945fcf5ef2aSThomas Huth return -1; 946fcf5ef2aSThomas Huth } 947fcf5ef2aSThomas Huth } 948fcf5ef2aSThomas Huth 949fcf5ef2aSThomas Huth return 0; 950fcf5ef2aSThomas Huth } 951fcf5ef2aSThomas Huth 952fcf5ef2aSThomas Huth /* 953fcf5ef2aSThomas Huth * Sync the KVM MP_STATE into QEMU 954fcf5ef2aSThomas Huth */ 955fcf5ef2aSThomas Huth int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu) 956fcf5ef2aSThomas Huth { 957fcf5ef2aSThomas Huth if (cap_has_mp_state) { 958fcf5ef2aSThomas Huth struct kvm_mp_state mp_state; 959fcf5ef2aSThomas Huth int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MP_STATE, &mp_state); 960fcf5ef2aSThomas Huth if (ret) { 961fcf5ef2aSThomas Huth fprintf(stderr, "%s: failed to get MP_STATE %d/%s\n", 962fcf5ef2aSThomas Huth __func__, ret, strerror(-ret)); 963fcf5ef2aSThomas Huth abort(); 964fcf5ef2aSThomas Huth } 965062ba099SAlex Bennée cpu->power_state = (mp_state.mp_state == KVM_MP_STATE_STOPPED) ? 966062ba099SAlex Bennée PSCI_OFF : PSCI_ON; 967fcf5ef2aSThomas Huth } 968fcf5ef2aSThomas Huth 969fcf5ef2aSThomas Huth return 0; 970fcf5ef2aSThomas Huth } 971fcf5ef2aSThomas Huth 97246512471SRichard Henderson /** 97346512471SRichard Henderson * kvm_arm_get_virtual_time: 97446512471SRichard Henderson * @cs: CPUState 97546512471SRichard Henderson * 97646512471SRichard Henderson * Gets the VCPU's virtual counter and stores it in the KVM CPU state. 97746512471SRichard Henderson */ 97846512471SRichard Henderson static void kvm_arm_get_virtual_time(CPUState *cs) 979e5ac4200SAndrew Jones { 980e5ac4200SAndrew Jones ARMCPU *cpu = ARM_CPU(cs); 981e5ac4200SAndrew Jones int ret; 982e5ac4200SAndrew Jones 983e5ac4200SAndrew Jones if (cpu->kvm_vtime_dirty) { 984e5ac4200SAndrew Jones return; 985e5ac4200SAndrew Jones } 986e5ac4200SAndrew Jones 98740d45b85SCornelia Huck ret = kvm_get_one_reg(cs, KVM_REG_ARM_TIMER_CNT, &cpu->kvm_vtime); 988e5ac4200SAndrew Jones if (ret) { 989e5ac4200SAndrew Jones error_report("Failed to get KVM_REG_ARM_TIMER_CNT"); 990e5ac4200SAndrew Jones abort(); 991e5ac4200SAndrew Jones } 992e5ac4200SAndrew Jones 993e5ac4200SAndrew Jones cpu->kvm_vtime_dirty = true; 994e5ac4200SAndrew Jones } 995e5ac4200SAndrew Jones 99646512471SRichard Henderson /** 99746512471SRichard Henderson * kvm_arm_put_virtual_time: 99846512471SRichard Henderson * @cs: CPUState 99946512471SRichard Henderson * 100046512471SRichard Henderson * Sets the VCPU's virtual counter to the value stored in the KVM CPU state. 100146512471SRichard Henderson */ 100246512471SRichard Henderson static void kvm_arm_put_virtual_time(CPUState *cs) 1003e5ac4200SAndrew Jones { 1004e5ac4200SAndrew Jones ARMCPU *cpu = ARM_CPU(cs); 1005e5ac4200SAndrew Jones int ret; 1006e5ac4200SAndrew Jones 1007e5ac4200SAndrew Jones if (!cpu->kvm_vtime_dirty) { 1008e5ac4200SAndrew Jones return; 1009e5ac4200SAndrew Jones } 1010e5ac4200SAndrew Jones 10116c8b9a74SCornelia Huck ret = kvm_set_one_reg(cs, KVM_REG_ARM_TIMER_CNT, &cpu->kvm_vtime); 1012e5ac4200SAndrew Jones if (ret) { 1013e5ac4200SAndrew Jones error_report("Failed to set KVM_REG_ARM_TIMER_CNT"); 1014e5ac4200SAndrew Jones abort(); 1015e5ac4200SAndrew Jones } 1016e5ac4200SAndrew Jones 1017e5ac4200SAndrew Jones cpu->kvm_vtime_dirty = false; 1018e5ac4200SAndrew Jones } 1019e5ac4200SAndrew Jones 1020202ccb6bSDongjiu Geng int kvm_put_vcpu_events(ARMCPU *cpu) 1021202ccb6bSDongjiu Geng { 1022202ccb6bSDongjiu Geng CPUARMState *env = &cpu->env; 1023202ccb6bSDongjiu Geng struct kvm_vcpu_events events; 1024202ccb6bSDongjiu Geng int ret; 1025202ccb6bSDongjiu Geng 1026202ccb6bSDongjiu Geng if (!kvm_has_vcpu_events()) { 1027202ccb6bSDongjiu Geng return 0; 1028202ccb6bSDongjiu Geng } 1029202ccb6bSDongjiu Geng 1030202ccb6bSDongjiu Geng memset(&events, 0, sizeof(events)); 1031202ccb6bSDongjiu Geng events.exception.serror_pending = env->serror.pending; 1032202ccb6bSDongjiu Geng 1033202ccb6bSDongjiu Geng /* Inject SError to guest with specified syndrome if host kernel 1034202ccb6bSDongjiu Geng * supports it, otherwise inject SError without syndrome. 1035202ccb6bSDongjiu Geng */ 1036202ccb6bSDongjiu Geng if (cap_has_inject_serror_esr) { 1037202ccb6bSDongjiu Geng events.exception.serror_has_esr = env->serror.has_esr; 1038202ccb6bSDongjiu Geng events.exception.serror_esr = env->serror.esr; 1039202ccb6bSDongjiu Geng } 1040202ccb6bSDongjiu Geng 1041202ccb6bSDongjiu Geng ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_VCPU_EVENTS, &events); 1042202ccb6bSDongjiu Geng if (ret) { 1043202ccb6bSDongjiu Geng error_report("failed to put vcpu events"); 1044202ccb6bSDongjiu Geng } 1045202ccb6bSDongjiu Geng 1046202ccb6bSDongjiu Geng return ret; 1047202ccb6bSDongjiu Geng } 1048202ccb6bSDongjiu Geng 1049202ccb6bSDongjiu Geng int kvm_get_vcpu_events(ARMCPU *cpu) 1050202ccb6bSDongjiu Geng { 1051202ccb6bSDongjiu Geng CPUARMState *env = &cpu->env; 1052202ccb6bSDongjiu Geng struct kvm_vcpu_events events; 1053202ccb6bSDongjiu Geng int ret; 1054202ccb6bSDongjiu Geng 1055202ccb6bSDongjiu Geng if (!kvm_has_vcpu_events()) { 1056202ccb6bSDongjiu Geng return 0; 1057202ccb6bSDongjiu Geng } 1058202ccb6bSDongjiu Geng 1059202ccb6bSDongjiu Geng memset(&events, 0, sizeof(events)); 1060202ccb6bSDongjiu Geng ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_VCPU_EVENTS, &events); 1061202ccb6bSDongjiu Geng if (ret) { 1062202ccb6bSDongjiu Geng error_report("failed to get vcpu events"); 1063202ccb6bSDongjiu Geng return ret; 1064202ccb6bSDongjiu Geng } 1065202ccb6bSDongjiu Geng 1066202ccb6bSDongjiu Geng env->serror.pending = events.exception.serror_pending; 1067202ccb6bSDongjiu Geng env->serror.has_esr = events.exception.serror_has_esr; 1068202ccb6bSDongjiu Geng env->serror.esr = events.exception.serror_esr; 1069202ccb6bSDongjiu Geng 1070202ccb6bSDongjiu Geng return 0; 1071202ccb6bSDongjiu Geng } 1072202ccb6bSDongjiu Geng 107320c83dc9SRichard Henderson #define ARM64_REG_ESR_EL1 ARM64_SYS_REG(3, 0, 5, 2, 0) 107420c83dc9SRichard Henderson #define ARM64_REG_TCR_EL1 ARM64_SYS_REG(3, 0, 2, 0, 2) 107520c83dc9SRichard Henderson 107620c83dc9SRichard Henderson /* 107720c83dc9SRichard Henderson * ESR_EL1 107820c83dc9SRichard Henderson * ISS encoding 107920c83dc9SRichard Henderson * AARCH64: DFSC, bits [5:0] 108020c83dc9SRichard Henderson * AARCH32: 108120c83dc9SRichard Henderson * TTBCR.EAE == 0 108220c83dc9SRichard Henderson * FS[4] - DFSR[10] 108320c83dc9SRichard Henderson * FS[3:0] - DFSR[3:0] 108420c83dc9SRichard Henderson * TTBCR.EAE == 1 108520c83dc9SRichard Henderson * FS, bits [5:0] 108620c83dc9SRichard Henderson */ 108720c83dc9SRichard Henderson #define ESR_DFSC(aarch64, lpae, v) \ 108820c83dc9SRichard Henderson ((aarch64 || (lpae)) ? ((v) & 0x3F) \ 108920c83dc9SRichard Henderson : (((v) >> 6) | ((v) & 0x1F))) 109020c83dc9SRichard Henderson 109120c83dc9SRichard Henderson #define ESR_DFSC_EXTABT(aarch64, lpae) \ 109220c83dc9SRichard Henderson ((aarch64) ? 0x10 : (lpae) ? 0x10 : 0x8) 109320c83dc9SRichard Henderson 109420c83dc9SRichard Henderson /** 109520c83dc9SRichard Henderson * kvm_arm_verify_ext_dabt_pending: 109620c83dc9SRichard Henderson * @cs: CPUState 109720c83dc9SRichard Henderson * 109820c83dc9SRichard Henderson * Verify the fault status code wrt the Ext DABT injection 109920c83dc9SRichard Henderson * 110020c83dc9SRichard Henderson * Returns: true if the fault status code is as expected, false otherwise 110120c83dc9SRichard Henderson */ 110220c83dc9SRichard Henderson static bool kvm_arm_verify_ext_dabt_pending(CPUState *cs) 110320c83dc9SRichard Henderson { 110420c83dc9SRichard Henderson uint64_t dfsr_val; 110520c83dc9SRichard Henderson 110620c83dc9SRichard Henderson if (!kvm_get_one_reg(cs, ARM64_REG_ESR_EL1, &dfsr_val)) { 110720c83dc9SRichard Henderson ARMCPU *cpu = ARM_CPU(cs); 110820c83dc9SRichard Henderson CPUARMState *env = &cpu->env; 110920c83dc9SRichard Henderson int aarch64_mode = arm_feature(env, ARM_FEATURE_AARCH64); 111020c83dc9SRichard Henderson int lpae = 0; 111120c83dc9SRichard Henderson 111220c83dc9SRichard Henderson if (!aarch64_mode) { 111320c83dc9SRichard Henderson uint64_t ttbcr; 111420c83dc9SRichard Henderson 111520c83dc9SRichard Henderson if (!kvm_get_one_reg(cs, ARM64_REG_TCR_EL1, &ttbcr)) { 111620c83dc9SRichard Henderson lpae = arm_feature(env, ARM_FEATURE_LPAE) 111720c83dc9SRichard Henderson && (ttbcr & TTBCR_EAE); 111820c83dc9SRichard Henderson } 111920c83dc9SRichard Henderson } 112020c83dc9SRichard Henderson /* 112120c83dc9SRichard Henderson * The verification here is based on the DFSC bits 112220c83dc9SRichard Henderson * of the ESR_EL1 reg only 112320c83dc9SRichard Henderson */ 112420c83dc9SRichard Henderson return (ESR_DFSC(aarch64_mode, lpae, dfsr_val) == 112520c83dc9SRichard Henderson ESR_DFSC_EXTABT(aarch64_mode, lpae)); 112620c83dc9SRichard Henderson } 112720c83dc9SRichard Henderson return false; 112820c83dc9SRichard Henderson } 112920c83dc9SRichard Henderson 1130fcf5ef2aSThomas Huth void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 1131fcf5ef2aSThomas Huth { 11321711bfa5SBeata Michalska ARMCPU *cpu = ARM_CPU(cs); 11331711bfa5SBeata Michalska CPUARMState *env = &cpu->env; 11341711bfa5SBeata Michalska 11351711bfa5SBeata Michalska if (unlikely(env->ext_dabt_raised)) { 11361711bfa5SBeata Michalska /* 11371711bfa5SBeata Michalska * Verifying that the ext DABT has been properly injected, 11381711bfa5SBeata Michalska * otherwise risking indefinitely re-running the faulting instruction 11391711bfa5SBeata Michalska * Covering a very narrow case for kernels 5.5..5.5.4 11401711bfa5SBeata Michalska * when injected abort was misconfigured to be 11411711bfa5SBeata Michalska * an IMPLEMENTATION DEFINED exception (for 32-bit EL1) 11421711bfa5SBeata Michalska */ 11431711bfa5SBeata Michalska if (!arm_feature(env, ARM_FEATURE_AARCH64) && 11441711bfa5SBeata Michalska unlikely(!kvm_arm_verify_ext_dabt_pending(cs))) { 11451711bfa5SBeata Michalska 11461711bfa5SBeata Michalska error_report("Data abort exception with no valid ISS generated by " 11471711bfa5SBeata Michalska "guest memory access. KVM unable to emulate faulting " 11481711bfa5SBeata Michalska "instruction. Failed to inject an external data abort " 11491711bfa5SBeata Michalska "into the guest."); 11501711bfa5SBeata Michalska abort(); 11511711bfa5SBeata Michalska } 11521711bfa5SBeata Michalska /* Clear the status */ 11531711bfa5SBeata Michalska env->ext_dabt_raised = 0; 11541711bfa5SBeata Michalska } 1155fcf5ef2aSThomas Huth } 1156fcf5ef2aSThomas Huth 1157fcf5ef2aSThomas Huth MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 1158fcf5ef2aSThomas Huth { 11595d721b78SAlexander Graf ARMCPU *cpu; 11605d721b78SAlexander Graf uint32_t switched_level; 11615d721b78SAlexander Graf 11625d721b78SAlexander Graf if (kvm_irqchip_in_kernel()) { 11635d721b78SAlexander Graf /* 11645d721b78SAlexander Graf * We only need to sync timer states with user-space interrupt 11655d721b78SAlexander Graf * controllers, so return early and save cycles if we don't. 11665d721b78SAlexander Graf */ 11675d721b78SAlexander Graf return MEMTXATTRS_UNSPECIFIED; 11685d721b78SAlexander Graf } 11695d721b78SAlexander Graf 11705d721b78SAlexander Graf cpu = ARM_CPU(cs); 11715d721b78SAlexander Graf 11725d721b78SAlexander Graf /* Synchronize our shadowed in-kernel device irq lines with the kvm ones */ 11735d721b78SAlexander Graf if (run->s.regs.device_irq_level != cpu->device_irq_level) { 11745d721b78SAlexander Graf switched_level = cpu->device_irq_level ^ run->s.regs.device_irq_level; 11755d721b78SAlexander Graf 11765d721b78SAlexander Graf qemu_mutex_lock_iothread(); 11775d721b78SAlexander Graf 11785d721b78SAlexander Graf if (switched_level & KVM_ARM_DEV_EL1_VTIMER) { 11795d721b78SAlexander Graf qemu_set_irq(cpu->gt_timer_outputs[GTIMER_VIRT], 11805d721b78SAlexander Graf !!(run->s.regs.device_irq_level & 11815d721b78SAlexander Graf KVM_ARM_DEV_EL1_VTIMER)); 11825d721b78SAlexander Graf switched_level &= ~KVM_ARM_DEV_EL1_VTIMER; 11835d721b78SAlexander Graf } 11845d721b78SAlexander Graf 11855d721b78SAlexander Graf if (switched_level & KVM_ARM_DEV_EL1_PTIMER) { 11865d721b78SAlexander Graf qemu_set_irq(cpu->gt_timer_outputs[GTIMER_PHYS], 11875d721b78SAlexander Graf !!(run->s.regs.device_irq_level & 11885d721b78SAlexander Graf KVM_ARM_DEV_EL1_PTIMER)); 11895d721b78SAlexander Graf switched_level &= ~KVM_ARM_DEV_EL1_PTIMER; 11905d721b78SAlexander Graf } 11915d721b78SAlexander Graf 1192b1659527SAndrew Jones if (switched_level & KVM_ARM_DEV_PMU) { 1193b1659527SAndrew Jones qemu_set_irq(cpu->pmu_interrupt, 1194b1659527SAndrew Jones !!(run->s.regs.device_irq_level & KVM_ARM_DEV_PMU)); 1195b1659527SAndrew Jones switched_level &= ~KVM_ARM_DEV_PMU; 1196b1659527SAndrew Jones } 11975d721b78SAlexander Graf 11985d721b78SAlexander Graf if (switched_level) { 11995d721b78SAlexander Graf qemu_log_mask(LOG_UNIMP, "%s: unhandled in-kernel device IRQ %x\n", 12005d721b78SAlexander Graf __func__, switched_level); 12015d721b78SAlexander Graf } 12025d721b78SAlexander Graf 12035d721b78SAlexander Graf /* We also mark unknown levels as processed to not waste cycles */ 12045d721b78SAlexander Graf cpu->device_irq_level = run->s.regs.device_irq_level; 12055d721b78SAlexander Graf qemu_mutex_unlock_iothread(); 12065d721b78SAlexander Graf } 12075d721b78SAlexander Graf 1208fcf5ef2aSThomas Huth return MEMTXATTRS_UNSPECIFIED; 1209fcf5ef2aSThomas Huth } 1210fcf5ef2aSThomas Huth 1211538f0497SPhilippe Mathieu-Daudé void kvm_arm_vm_state_change(void *opaque, bool running, RunState state) 1212e5ac4200SAndrew Jones { 1213e5ac4200SAndrew Jones CPUState *cs = opaque; 1214e5ac4200SAndrew Jones ARMCPU *cpu = ARM_CPU(cs); 1215e5ac4200SAndrew Jones 1216e5ac4200SAndrew Jones if (running) { 1217e5ac4200SAndrew Jones if (cpu->kvm_adjvtime) { 1218e5ac4200SAndrew Jones kvm_arm_put_virtual_time(cs); 1219e5ac4200SAndrew Jones } 1220e5ac4200SAndrew Jones } else { 1221e5ac4200SAndrew Jones if (cpu->kvm_adjvtime) { 1222e5ac4200SAndrew Jones kvm_arm_get_virtual_time(cs); 1223e5ac4200SAndrew Jones } 1224e5ac4200SAndrew Jones } 1225e5ac4200SAndrew Jones } 1226fcf5ef2aSThomas Huth 1227694bcaa8SBeata Michalska /** 1228694bcaa8SBeata Michalska * kvm_arm_handle_dabt_nisv: 1229694bcaa8SBeata Michalska * @cs: CPUState 1230694bcaa8SBeata Michalska * @esr_iss: ISS encoding (limited) for the exception from Data Abort 1231694bcaa8SBeata Michalska * ISV bit set to '0b0' -> no valid instruction syndrome 1232694bcaa8SBeata Michalska * @fault_ipa: faulting address for the synchronous data abort 1233694bcaa8SBeata Michalska * 1234694bcaa8SBeata Michalska * Returns: 0 if the exception has been handled, < 0 otherwise 1235694bcaa8SBeata Michalska */ 1236694bcaa8SBeata Michalska static int kvm_arm_handle_dabt_nisv(CPUState *cs, uint64_t esr_iss, 1237694bcaa8SBeata Michalska uint64_t fault_ipa) 1238694bcaa8SBeata Michalska { 12391711bfa5SBeata Michalska ARMCPU *cpu = ARM_CPU(cs); 12401711bfa5SBeata Michalska CPUARMState *env = &cpu->env; 1241694bcaa8SBeata Michalska /* 1242694bcaa8SBeata Michalska * Request KVM to inject the external data abort into the guest 1243694bcaa8SBeata Michalska */ 1244694bcaa8SBeata Michalska if (cap_has_inject_ext_dabt) { 1245694bcaa8SBeata Michalska struct kvm_vcpu_events events = { }; 1246694bcaa8SBeata Michalska /* 1247694bcaa8SBeata Michalska * The external data abort event will be handled immediately by KVM 1248694bcaa8SBeata Michalska * using the address fault that triggered the exit on given VCPU. 1249694bcaa8SBeata Michalska * Requesting injection of the external data abort does not rely 1250694bcaa8SBeata Michalska * on any other VCPU state. Therefore, in this particular case, the VCPU 1251694bcaa8SBeata Michalska * synchronization can be exceptionally skipped. 1252694bcaa8SBeata Michalska */ 1253694bcaa8SBeata Michalska events.exception.ext_dabt_pending = 1; 1254694bcaa8SBeata Michalska /* KVM_CAP_ARM_INJECT_EXT_DABT implies KVM_CAP_VCPU_EVENTS */ 12551711bfa5SBeata Michalska if (!kvm_vcpu_ioctl(cs, KVM_SET_VCPU_EVENTS, &events)) { 12561711bfa5SBeata Michalska env->ext_dabt_raised = 1; 12571711bfa5SBeata Michalska return 0; 12581711bfa5SBeata Michalska } 1259694bcaa8SBeata Michalska } else { 1260694bcaa8SBeata Michalska error_report("Data abort exception triggered by guest memory access " 1261694bcaa8SBeata Michalska "at physical address: 0x" TARGET_FMT_lx, 1262694bcaa8SBeata Michalska (target_ulong)fault_ipa); 1263694bcaa8SBeata Michalska error_printf("KVM unable to emulate faulting instruction.\n"); 1264694bcaa8SBeata Michalska } 1265694bcaa8SBeata Michalska return -1; 1266694bcaa8SBeata Michalska } 1267694bcaa8SBeata Michalska 12685cba8f26SRichard Henderson /** 12695cba8f26SRichard Henderson * kvm_arm_handle_debug: 12705cba8f26SRichard Henderson * @cs: CPUState 12715cba8f26SRichard Henderson * @debug_exit: debug part of the KVM exit structure 12725cba8f26SRichard Henderson * 12735cba8f26SRichard Henderson * Returns: TRUE if the debug exception was handled. 12745cba8f26SRichard Henderson * 12755cba8f26SRichard Henderson * See v8 ARM ARM D7.2.27 ESR_ELx, Exception Syndrome Register 12765cba8f26SRichard Henderson * 12775cba8f26SRichard Henderson * To minimise translating between kernel and user-space the kernel 12785cba8f26SRichard Henderson * ABI just provides user-space with the full exception syndrome 12795cba8f26SRichard Henderson * register value to be decoded in QEMU. 12805cba8f26SRichard Henderson */ 12815cba8f26SRichard Henderson static bool kvm_arm_handle_debug(CPUState *cs, 12825cba8f26SRichard Henderson struct kvm_debug_exit_arch *debug_exit) 12835cba8f26SRichard Henderson { 12845cba8f26SRichard Henderson int hsr_ec = syn_get_ec(debug_exit->hsr); 12855cba8f26SRichard Henderson ARMCPU *cpu = ARM_CPU(cs); 12865cba8f26SRichard Henderson CPUARMState *env = &cpu->env; 12875cba8f26SRichard Henderson 12885cba8f26SRichard Henderson /* Ensure PC is synchronised */ 12895cba8f26SRichard Henderson kvm_cpu_synchronize_state(cs); 12905cba8f26SRichard Henderson 12915cba8f26SRichard Henderson switch (hsr_ec) { 12925cba8f26SRichard Henderson case EC_SOFTWARESTEP: 12935cba8f26SRichard Henderson if (cs->singlestep_enabled) { 12945cba8f26SRichard Henderson return true; 12955cba8f26SRichard Henderson } else { 12965cba8f26SRichard Henderson /* 12975cba8f26SRichard Henderson * The kernel should have suppressed the guest's ability to 12985cba8f26SRichard Henderson * single step at this point so something has gone wrong. 12995cba8f26SRichard Henderson */ 13005cba8f26SRichard Henderson error_report("%s: guest single-step while debugging unsupported" 13015cba8f26SRichard Henderson " (%"PRIx64", %"PRIx32")", 13025cba8f26SRichard Henderson __func__, env->pc, debug_exit->hsr); 13035cba8f26SRichard Henderson return false; 13045cba8f26SRichard Henderson } 13055cba8f26SRichard Henderson break; 13065cba8f26SRichard Henderson case EC_AA64_BKPT: 13075cba8f26SRichard Henderson if (kvm_find_sw_breakpoint(cs, env->pc)) { 13085cba8f26SRichard Henderson return true; 13095cba8f26SRichard Henderson } 13105cba8f26SRichard Henderson break; 13115cba8f26SRichard Henderson case EC_BREAKPOINT: 13125cba8f26SRichard Henderson if (find_hw_breakpoint(cs, env->pc)) { 13135cba8f26SRichard Henderson return true; 13145cba8f26SRichard Henderson } 13155cba8f26SRichard Henderson break; 13165cba8f26SRichard Henderson case EC_WATCHPOINT: 13175cba8f26SRichard Henderson { 13185cba8f26SRichard Henderson CPUWatchpoint *wp = find_hw_watchpoint(cs, debug_exit->far); 13195cba8f26SRichard Henderson if (wp) { 13205cba8f26SRichard Henderson cs->watchpoint_hit = wp; 13215cba8f26SRichard Henderson return true; 13225cba8f26SRichard Henderson } 13235cba8f26SRichard Henderson break; 13245cba8f26SRichard Henderson } 13255cba8f26SRichard Henderson default: 13265cba8f26SRichard Henderson error_report("%s: unhandled debug exit (%"PRIx32", %"PRIx64")", 13275cba8f26SRichard Henderson __func__, debug_exit->hsr, env->pc); 13285cba8f26SRichard Henderson } 13295cba8f26SRichard Henderson 13305cba8f26SRichard Henderson /* If we are not handling the debug exception it must belong to 13315cba8f26SRichard Henderson * the guest. Let's re-use the existing TCG interrupt code to set 13325cba8f26SRichard Henderson * everything up properly. 13335cba8f26SRichard Henderson */ 13345cba8f26SRichard Henderson cs->exception_index = EXCP_BKPT; 13355cba8f26SRichard Henderson env->exception.syndrome = debug_exit->hsr; 13365cba8f26SRichard Henderson env->exception.vaddress = debug_exit->far; 13375cba8f26SRichard Henderson env->exception.target_el = 1; 13385cba8f26SRichard Henderson qemu_mutex_lock_iothread(); 13395cba8f26SRichard Henderson arm_cpu_do_interrupt(cs); 13405cba8f26SRichard Henderson qemu_mutex_unlock_iothread(); 13415cba8f26SRichard Henderson 13425cba8f26SRichard Henderson return false; 13435cba8f26SRichard Henderson } 13445cba8f26SRichard Henderson 1345fcf5ef2aSThomas Huth int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 1346fcf5ef2aSThomas Huth { 1347fcf5ef2aSThomas Huth int ret = 0; 1348fcf5ef2aSThomas Huth 1349fcf5ef2aSThomas Huth switch (run->exit_reason) { 1350fcf5ef2aSThomas Huth case KVM_EXIT_DEBUG: 1351fcf5ef2aSThomas Huth if (kvm_arm_handle_debug(cs, &run->debug.arch)) { 1352fcf5ef2aSThomas Huth ret = EXCP_DEBUG; 1353fcf5ef2aSThomas Huth } /* otherwise return to guest */ 1354fcf5ef2aSThomas Huth break; 1355694bcaa8SBeata Michalska case KVM_EXIT_ARM_NISV: 1356694bcaa8SBeata Michalska /* External DABT with no valid iss to decode */ 1357694bcaa8SBeata Michalska ret = kvm_arm_handle_dabt_nisv(cs, run->arm_nisv.esr_iss, 1358694bcaa8SBeata Michalska run->arm_nisv.fault_ipa); 1359694bcaa8SBeata Michalska break; 1360fcf5ef2aSThomas Huth default: 1361fcf5ef2aSThomas Huth qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", 1362fcf5ef2aSThomas Huth __func__, run->exit_reason); 1363fcf5ef2aSThomas Huth break; 1364fcf5ef2aSThomas Huth } 1365fcf5ef2aSThomas Huth return ret; 1366fcf5ef2aSThomas Huth } 1367fcf5ef2aSThomas Huth 1368fcf5ef2aSThomas Huth bool kvm_arch_stop_on_emulation_error(CPUState *cs) 1369fcf5ef2aSThomas Huth { 1370fcf5ef2aSThomas Huth return true; 1371fcf5ef2aSThomas Huth } 1372fcf5ef2aSThomas Huth 1373fcf5ef2aSThomas Huth int kvm_arch_process_async_events(CPUState *cs) 1374fcf5ef2aSThomas Huth { 1375fcf5ef2aSThomas Huth return 0; 1376fcf5ef2aSThomas Huth } 1377fcf5ef2aSThomas Huth 1378ec4145f7SRichard Henderson /** 1379ea79c599SRichard Henderson * kvm_arm_hw_debug_active: 1380ea79c599SRichard Henderson * @cs: CPU State 1381ea79c599SRichard Henderson * 1382ea79c599SRichard Henderson * Return: TRUE if any hardware breakpoints in use. 1383ea79c599SRichard Henderson */ 1384ea79c599SRichard Henderson static bool kvm_arm_hw_debug_active(CPUState *cs) 1385ea79c599SRichard Henderson { 1386ea79c599SRichard Henderson return ((cur_hw_wps > 0) || (cur_hw_bps > 0)); 1387ea79c599SRichard Henderson } 1388ea79c599SRichard Henderson 1389ea79c599SRichard Henderson /** 1390ec4145f7SRichard Henderson * kvm_arm_copy_hw_debug_data: 1391ec4145f7SRichard Henderson * @ptr: kvm_guest_debug_arch structure 1392ec4145f7SRichard Henderson * 1393ec4145f7SRichard Henderson * Copy the architecture specific debug registers into the 1394ec4145f7SRichard Henderson * kvm_guest_debug ioctl structure. 1395ec4145f7SRichard Henderson */ 1396ec4145f7SRichard Henderson static void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr) 1397ec4145f7SRichard Henderson { 1398ec4145f7SRichard Henderson int i; 1399ec4145f7SRichard Henderson memset(ptr, 0, sizeof(struct kvm_guest_debug_arch)); 1400ec4145f7SRichard Henderson 1401ec4145f7SRichard Henderson for (i = 0; i < max_hw_wps; i++) { 1402ec4145f7SRichard Henderson HWWatchpoint *wp = get_hw_wp(i); 1403ec4145f7SRichard Henderson ptr->dbg_wcr[i] = wp->wcr; 1404ec4145f7SRichard Henderson ptr->dbg_wvr[i] = wp->wvr; 1405ec4145f7SRichard Henderson } 1406ec4145f7SRichard Henderson for (i = 0; i < max_hw_bps; i++) { 1407ec4145f7SRichard Henderson HWBreakpoint *bp = get_hw_bp(i); 1408ec4145f7SRichard Henderson ptr->dbg_bcr[i] = bp->bcr; 1409ec4145f7SRichard Henderson ptr->dbg_bvr[i] = bp->bvr; 1410ec4145f7SRichard Henderson } 1411ec4145f7SRichard Henderson } 1412ec4145f7SRichard Henderson 1413fcf5ef2aSThomas Huth void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) 1414fcf5ef2aSThomas Huth { 1415fcf5ef2aSThomas Huth if (kvm_sw_breakpoints_active(cs)) { 1416fcf5ef2aSThomas Huth dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; 1417fcf5ef2aSThomas Huth } 1418fcf5ef2aSThomas Huth if (kvm_arm_hw_debug_active(cs)) { 1419fcf5ef2aSThomas Huth dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW; 1420fcf5ef2aSThomas Huth kvm_arm_copy_hw_debug_data(&dbg->arch); 1421fcf5ef2aSThomas Huth } 1422fcf5ef2aSThomas Huth } 1423fcf5ef2aSThomas Huth 1424fcf5ef2aSThomas Huth void kvm_arch_init_irq_routing(KVMState *s) 1425fcf5ef2aSThomas Huth { 1426fcf5ef2aSThomas Huth } 1427fcf5ef2aSThomas Huth 14284376c40dSPaolo Bonzini int kvm_arch_irqchip_create(KVMState *s) 1429fcf5ef2aSThomas Huth { 14304376c40dSPaolo Bonzini if (kvm_kernel_irqchip_split()) { 143147c182feSCornelia Huck error_report("-machine kernel_irqchip=split is not supported on ARM."); 1432fcf5ef2aSThomas Huth exit(1); 1433fcf5ef2aSThomas Huth } 1434fcf5ef2aSThomas Huth 1435fcf5ef2aSThomas Huth /* If we can create the VGIC using the newer device control API, we 1436fcf5ef2aSThomas Huth * let the device do this when it initializes itself, otherwise we 1437fcf5ef2aSThomas Huth * fall back to the old API */ 1438fcf5ef2aSThomas Huth return kvm_check_extension(s, KVM_CAP_DEVICE_CTRL); 1439fcf5ef2aSThomas Huth } 1440fcf5ef2aSThomas Huth 1441fcf5ef2aSThomas Huth int kvm_arm_vgic_probe(void) 1442fcf5ef2aSThomas Huth { 1443d45efe47SEric Auger int val = 0; 1444d45efe47SEric Auger 1445fcf5ef2aSThomas Huth if (kvm_create_device(kvm_state, 1446fcf5ef2aSThomas Huth KVM_DEV_TYPE_ARM_VGIC_V3, true) == 0) { 1447d45efe47SEric Auger val |= KVM_ARM_VGIC_V3; 1448fcf5ef2aSThomas Huth } 1449d45efe47SEric Auger if (kvm_create_device(kvm_state, 1450d45efe47SEric Auger KVM_DEV_TYPE_ARM_VGIC_V2, true) == 0) { 1451d45efe47SEric Auger val |= KVM_ARM_VGIC_V2; 1452d45efe47SEric Auger } 1453d45efe47SEric Auger return val; 1454fcf5ef2aSThomas Huth } 1455fcf5ef2aSThomas Huth 1456f6530926SEric Auger int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level) 1457f6530926SEric Auger { 1458f6530926SEric Auger int kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT) | irq; 1459f6530926SEric Auger int cpu_idx1 = cpu % 256; 1460f6530926SEric Auger int cpu_idx2 = cpu / 256; 1461f6530926SEric Auger 1462f6530926SEric Auger kvm_irq |= (cpu_idx1 << KVM_ARM_IRQ_VCPU_SHIFT) | 1463f6530926SEric Auger (cpu_idx2 << KVM_ARM_IRQ_VCPU2_SHIFT); 1464f6530926SEric Auger 1465f6530926SEric Auger return kvm_set_irq(kvm_state, kvm_irq, !!level); 1466f6530926SEric Auger } 1467f6530926SEric Auger 1468fcf5ef2aSThomas Huth int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 1469fcf5ef2aSThomas Huth uint64_t address, uint32_t data, PCIDevice *dev) 1470fcf5ef2aSThomas Huth { 1471b05c81d2SEric Auger AddressSpace *as = pci_device_iommu_address_space(dev); 1472b05c81d2SEric Auger hwaddr xlat, len, doorbell_gpa; 1473b05c81d2SEric Auger MemoryRegionSection mrs; 1474b05c81d2SEric Auger MemoryRegion *mr; 1475b05c81d2SEric Auger 1476b05c81d2SEric Auger if (as == &address_space_memory) { 1477fcf5ef2aSThomas Huth return 0; 1478fcf5ef2aSThomas Huth } 1479fcf5ef2aSThomas Huth 1480b05c81d2SEric Auger /* MSI doorbell address is translated by an IOMMU */ 1481b05c81d2SEric Auger 1482dfa0d9b8SHamza Mahfooz RCU_READ_LOCK_GUARD(); 1483dfa0d9b8SHamza Mahfooz 1484bc6b1cecSPeter Maydell mr = address_space_translate(as, address, &xlat, &len, true, 1485bc6b1cecSPeter Maydell MEMTXATTRS_UNSPECIFIED); 1486dfa0d9b8SHamza Mahfooz 1487b05c81d2SEric Auger if (!mr) { 1488dfa0d9b8SHamza Mahfooz return 1; 1489b05c81d2SEric Auger } 1490dfa0d9b8SHamza Mahfooz 1491b05c81d2SEric Auger mrs = memory_region_find(mr, xlat, 1); 1492dfa0d9b8SHamza Mahfooz 1493b05c81d2SEric Auger if (!mrs.mr) { 1494dfa0d9b8SHamza Mahfooz return 1; 1495b05c81d2SEric Auger } 1496b05c81d2SEric Auger 1497b05c81d2SEric Auger doorbell_gpa = mrs.offset_within_address_space; 1498b05c81d2SEric Auger memory_region_unref(mrs.mr); 1499b05c81d2SEric Auger 1500b05c81d2SEric Auger route->u.msi.address_lo = doorbell_gpa; 1501b05c81d2SEric Auger route->u.msi.address_hi = doorbell_gpa >> 32; 1502b05c81d2SEric Auger 1503b05c81d2SEric Auger trace_kvm_arm_fixup_msi_route(address, doorbell_gpa); 1504b05c81d2SEric Auger 1505dfa0d9b8SHamza Mahfooz return 0; 1506b05c81d2SEric Auger } 1507b05c81d2SEric Auger 1508fcf5ef2aSThomas Huth int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 1509fcf5ef2aSThomas Huth int vector, PCIDevice *dev) 1510fcf5ef2aSThomas Huth { 1511fcf5ef2aSThomas Huth return 0; 1512fcf5ef2aSThomas Huth } 1513fcf5ef2aSThomas Huth 1514fcf5ef2aSThomas Huth int kvm_arch_release_virq_post(int virq) 1515fcf5ef2aSThomas Huth { 1516fcf5ef2aSThomas Huth return 0; 1517fcf5ef2aSThomas Huth } 1518fcf5ef2aSThomas Huth 1519fcf5ef2aSThomas Huth int kvm_arch_msi_data_to_gsi(uint32_t data) 1520fcf5ef2aSThomas Huth { 1521fcf5ef2aSThomas Huth return (data - 32) & 0xffff; 1522fcf5ef2aSThomas Huth } 152392a5199bSTom Lendacky 152492a5199bSTom Lendacky bool kvm_arch_cpu_check_are_resettable(void) 152592a5199bSTom Lendacky { 152692a5199bSTom Lendacky return true; 152792a5199bSTom Lendacky } 15283dba0a33SPaolo Bonzini 1529c8f2eb5dSShameer Kolothum static void kvm_arch_get_eager_split_size(Object *obj, Visitor *v, 1530c8f2eb5dSShameer Kolothum const char *name, void *opaque, 1531c8f2eb5dSShameer Kolothum Error **errp) 1532c8f2eb5dSShameer Kolothum { 1533c8f2eb5dSShameer Kolothum KVMState *s = KVM_STATE(obj); 1534c8f2eb5dSShameer Kolothum uint64_t value = s->kvm_eager_split_size; 1535c8f2eb5dSShameer Kolothum 1536c8f2eb5dSShameer Kolothum visit_type_size(v, name, &value, errp); 1537c8f2eb5dSShameer Kolothum } 1538c8f2eb5dSShameer Kolothum 1539c8f2eb5dSShameer Kolothum static void kvm_arch_set_eager_split_size(Object *obj, Visitor *v, 1540c8f2eb5dSShameer Kolothum const char *name, void *opaque, 1541c8f2eb5dSShameer Kolothum Error **errp) 1542c8f2eb5dSShameer Kolothum { 1543c8f2eb5dSShameer Kolothum KVMState *s = KVM_STATE(obj); 1544c8f2eb5dSShameer Kolothum uint64_t value; 1545c8f2eb5dSShameer Kolothum 1546c8f2eb5dSShameer Kolothum if (s->fd != -1) { 1547c8f2eb5dSShameer Kolothum error_setg(errp, "Unable to set early-split-size after KVM has been initialized"); 1548c8f2eb5dSShameer Kolothum return; 1549c8f2eb5dSShameer Kolothum } 1550c8f2eb5dSShameer Kolothum 1551c8f2eb5dSShameer Kolothum if (!visit_type_size(v, name, &value, errp)) { 1552c8f2eb5dSShameer Kolothum return; 1553c8f2eb5dSShameer Kolothum } 1554c8f2eb5dSShameer Kolothum 1555c8f2eb5dSShameer Kolothum if (value && !is_power_of_2(value)) { 1556c8f2eb5dSShameer Kolothum error_setg(errp, "early-split-size must be a power of two"); 1557c8f2eb5dSShameer Kolothum return; 1558c8f2eb5dSShameer Kolothum } 1559c8f2eb5dSShameer Kolothum 1560c8f2eb5dSShameer Kolothum s->kvm_eager_split_size = value; 1561c8f2eb5dSShameer Kolothum } 1562c8f2eb5dSShameer Kolothum 15633dba0a33SPaolo Bonzini void kvm_arch_accel_class_init(ObjectClass *oc) 15643dba0a33SPaolo Bonzini { 1565c8f2eb5dSShameer Kolothum object_class_property_add(oc, "eager-split-size", "size", 1566c8f2eb5dSShameer Kolothum kvm_arch_get_eager_split_size, 1567c8f2eb5dSShameer Kolothum kvm_arch_set_eager_split_size, NULL, NULL); 1568c8f2eb5dSShameer Kolothum 1569c8f2eb5dSShameer Kolothum object_class_property_set_description(oc, "eager-split-size", 1570c8f2eb5dSShameer Kolothum "Eager Page Split chunk size for hugepages. (default: 0, disabled)"); 15713dba0a33SPaolo Bonzini } 1572