17c0e8b0cSWill Deacon #include "kvm/kvm.h" 27c0e8b0cSWill Deacon #include "kvm/kvm-cpu.h" 37c0e8b0cSWill Deacon 47c0e8b0cSWill Deacon static int debug_fd; 57c0e8b0cSWill Deacon 67c0e8b0cSWill Deacon void kvm_cpu__set_debug_fd(int fd) 77c0e8b0cSWill Deacon { 87c0e8b0cSWill Deacon debug_fd = fd; 97c0e8b0cSWill Deacon } 107c0e8b0cSWill Deacon 117c0e8b0cSWill Deacon int kvm_cpu__get_debug_fd(void) 127c0e8b0cSWill Deacon { 137c0e8b0cSWill Deacon return debug_fd; 147c0e8b0cSWill Deacon } 157c0e8b0cSWill Deacon 16*85bd726aSAnup Patel static struct kvm_arm_target *kvm_arm_generic_target; 177c0e8b0cSWill Deacon static struct kvm_arm_target *kvm_arm_targets[KVM_ARM_NUM_TARGETS]; 18*85bd726aSAnup Patel 19*85bd726aSAnup Patel void kvm_cpu__set_kvm_arm_generic_target(struct kvm_arm_target *target) 20*85bd726aSAnup Patel { 21*85bd726aSAnup Patel kvm_arm_generic_target = target; 22*85bd726aSAnup Patel } 23*85bd726aSAnup Patel 247c0e8b0cSWill Deacon int kvm_cpu__register_kvm_arm_target(struct kvm_arm_target *target) 257c0e8b0cSWill Deacon { 267c0e8b0cSWill Deacon unsigned int i = 0; 277c0e8b0cSWill Deacon 287c0e8b0cSWill Deacon for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) { 297c0e8b0cSWill Deacon if (!kvm_arm_targets[i]) { 307c0e8b0cSWill Deacon kvm_arm_targets[i] = target; 317c0e8b0cSWill Deacon return 0; 327c0e8b0cSWill Deacon } 337c0e8b0cSWill Deacon } 347c0e8b0cSWill Deacon 357c0e8b0cSWill Deacon return -ENOSPC; 367c0e8b0cSWill Deacon } 377c0e8b0cSWill Deacon 387c0e8b0cSWill Deacon struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id) 397c0e8b0cSWill Deacon { 409b47146bSMarc Zyngier struct kvm_arm_target *target; 417c0e8b0cSWill Deacon struct kvm_cpu *vcpu; 427c0e8b0cSWill Deacon int coalesced_offset, mmap_size, err = -1; 437c0e8b0cSWill Deacon unsigned int i; 44*85bd726aSAnup Patel struct kvm_vcpu_init preferred_init; 4561076240SWill Deacon struct kvm_vcpu_init vcpu_init = { 4661076240SWill Deacon .features = ARM_VCPU_FEATURE_FLAGS(kvm, cpu_id) 4761076240SWill Deacon }; 487c0e8b0cSWill Deacon 497c0e8b0cSWill Deacon vcpu = calloc(1, sizeof(struct kvm_cpu)); 507c0e8b0cSWill Deacon if (!vcpu) 517c0e8b0cSWill Deacon return NULL; 527c0e8b0cSWill Deacon 537c0e8b0cSWill Deacon vcpu->vcpu_fd = ioctl(kvm->vm_fd, KVM_CREATE_VCPU, cpu_id); 547c0e8b0cSWill Deacon if (vcpu->vcpu_fd < 0) 557c0e8b0cSWill Deacon die_perror("KVM_CREATE_VCPU ioctl"); 567c0e8b0cSWill Deacon 577c0e8b0cSWill Deacon mmap_size = ioctl(kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0); 587c0e8b0cSWill Deacon if (mmap_size < 0) 597c0e8b0cSWill Deacon die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl"); 607c0e8b0cSWill Deacon 617c0e8b0cSWill Deacon vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED, 627c0e8b0cSWill Deacon vcpu->vcpu_fd, 0); 637c0e8b0cSWill Deacon if (vcpu->kvm_run == MAP_FAILED) 647c0e8b0cSWill Deacon die("unable to mmap vcpu fd"); 657c0e8b0cSWill Deacon 66*85bd726aSAnup Patel /* 67*85bd726aSAnup Patel * If the preferred target ioctl is successful then 68*85bd726aSAnup Patel * use preferred target else try each and every target type 69*85bd726aSAnup Patel */ 70*85bd726aSAnup Patel err = ioctl(kvm->vm_fd, KVM_ARM_PREFERRED_TARGET, &preferred_init); 71*85bd726aSAnup Patel if (!err) { 72*85bd726aSAnup Patel /* Match preferred target CPU type. */ 73*85bd726aSAnup Patel target = NULL; 74*85bd726aSAnup Patel for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) { 75*85bd726aSAnup Patel if (!kvm_arm_targets[i]) 76*85bd726aSAnup Patel continue; 77*85bd726aSAnup Patel if (kvm_arm_targets[i]->id == preferred_init.target) { 78*85bd726aSAnup Patel target = kvm_arm_targets[i]; 79*85bd726aSAnup Patel break; 80*85bd726aSAnup Patel } 81*85bd726aSAnup Patel } 82*85bd726aSAnup Patel if (!target) { 83*85bd726aSAnup Patel target = kvm_arm_generic_target; 84*85bd726aSAnup Patel vcpu_init.target = preferred_init.target; 85*85bd726aSAnup Patel } else { 86*85bd726aSAnup Patel vcpu_init.target = target->id; 87*85bd726aSAnup Patel } 88*85bd726aSAnup Patel err = ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init); 89*85bd726aSAnup Patel } else { 907c0e8b0cSWill Deacon /* Find an appropriate target CPU type. */ 917c0e8b0cSWill Deacon for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) { 928d0413d2SMarc Zyngier if (!kvm_arm_targets[i]) 938d0413d2SMarc Zyngier continue; 949b47146bSMarc Zyngier target = kvm_arm_targets[i]; 959b47146bSMarc Zyngier vcpu_init.target = target->id; 967c0e8b0cSWill Deacon err = ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init); 977c0e8b0cSWill Deacon if (!err) 987c0e8b0cSWill Deacon break; 997c0e8b0cSWill Deacon } 100*85bd726aSAnup Patel if (err) 101*85bd726aSAnup Patel die("Unable to find matching target"); 102*85bd726aSAnup Patel } 1037c0e8b0cSWill Deacon 1049b47146bSMarc Zyngier if (err || target->init(vcpu)) 105*85bd726aSAnup Patel die("Unable to initialise vcpu"); 1067c0e8b0cSWill Deacon 1077c0e8b0cSWill Deacon coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, 1087c0e8b0cSWill Deacon KVM_CAP_COALESCED_MMIO); 1097c0e8b0cSWill Deacon if (coalesced_offset) 1107c0e8b0cSWill Deacon vcpu->ring = (void *)vcpu->kvm_run + 1117c0e8b0cSWill Deacon (coalesced_offset * PAGE_SIZE); 1127c0e8b0cSWill Deacon 1137c0e8b0cSWill Deacon /* Populate the vcpu structure. */ 1147c0e8b0cSWill Deacon vcpu->kvm = kvm; 1157c0e8b0cSWill Deacon vcpu->cpu_id = cpu_id; 116*85bd726aSAnup Patel vcpu->cpu_type = vcpu_init.target; 1179b47146bSMarc Zyngier vcpu->cpu_compatible = target->compatible; 1187c0e8b0cSWill Deacon vcpu->is_running = true; 119*85bd726aSAnup Patel 1207c0e8b0cSWill Deacon return vcpu; 1217c0e8b0cSWill Deacon } 1227c0e8b0cSWill Deacon 1237c0e8b0cSWill Deacon void kvm_cpu__arch_nmi(struct kvm_cpu *cpu) 1247c0e8b0cSWill Deacon { 1257c0e8b0cSWill Deacon } 1267c0e8b0cSWill Deacon 1277c0e8b0cSWill Deacon void kvm_cpu__delete(struct kvm_cpu *vcpu) 1287c0e8b0cSWill Deacon { 1297c0e8b0cSWill Deacon free(vcpu); 1307c0e8b0cSWill Deacon } 1317c0e8b0cSWill Deacon 1327c0e8b0cSWill Deacon bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu) 1337c0e8b0cSWill Deacon { 1347c0e8b0cSWill Deacon return false; 1357c0e8b0cSWill Deacon } 1367c0e8b0cSWill Deacon 1379b735910SMarc Zyngier bool kvm_cpu__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, 1389b735910SMarc Zyngier u32 len, u8 is_write) 1397c0e8b0cSWill Deacon { 140d8bd1e1fSWill Deacon if (arm_addr_in_virtio_mmio_region(phys_addr)) { 1419b735910SMarc Zyngier return kvm__emulate_mmio(vcpu, phys_addr, data, len, is_write); 142d8bd1e1fSWill Deacon } else if (arm_addr_in_ioport_region(phys_addr)) { 143d8bd1e1fSWill Deacon int direction = is_write ? KVM_EXIT_IO_OUT : KVM_EXIT_IO_IN; 144c3e5e101SWill Deacon u16 port = (phys_addr - KVM_IOPORT_AREA) & USHRT_MAX; 1454123ca55SMarc Zyngier return kvm__emulate_io(vcpu, port, data, direction, len, 1); 146fcc922bfSWill Deacon } else if (arm_addr_in_pci_region(phys_addr)) { 1479b735910SMarc Zyngier return kvm__emulate_mmio(vcpu, phys_addr, data, len, is_write); 148d8bd1e1fSWill Deacon } 1497c0e8b0cSWill Deacon 1507c0e8b0cSWill Deacon return false; 1517c0e8b0cSWill Deacon } 1527c0e8b0cSWill Deacon 1537c0e8b0cSWill Deacon void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu) 1547c0e8b0cSWill Deacon { 1557c0e8b0cSWill Deacon } 156