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 167c0e8b0cSWill Deacon static struct kvm_arm_target *kvm_arm_targets[KVM_ARM_NUM_TARGETS]; 177c0e8b0cSWill Deacon int kvm_cpu__register_kvm_arm_target(struct kvm_arm_target *target) 187c0e8b0cSWill Deacon { 197c0e8b0cSWill Deacon unsigned int i = 0; 207c0e8b0cSWill Deacon 217c0e8b0cSWill Deacon for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) { 227c0e8b0cSWill Deacon if (!kvm_arm_targets[i]) { 237c0e8b0cSWill Deacon kvm_arm_targets[i] = target; 247c0e8b0cSWill Deacon return 0; 257c0e8b0cSWill Deacon } 267c0e8b0cSWill Deacon } 277c0e8b0cSWill Deacon 287c0e8b0cSWill Deacon return -ENOSPC; 297c0e8b0cSWill Deacon } 307c0e8b0cSWill Deacon 317c0e8b0cSWill Deacon struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id) 327c0e8b0cSWill Deacon { 33*9b47146bSMarc Zyngier struct kvm_arm_target *target; 347c0e8b0cSWill Deacon struct kvm_cpu *vcpu; 357c0e8b0cSWill Deacon int coalesced_offset, mmap_size, err = -1; 367c0e8b0cSWill Deacon unsigned int i; 3761076240SWill Deacon struct kvm_vcpu_init vcpu_init = { 3861076240SWill Deacon .features = ARM_VCPU_FEATURE_FLAGS(kvm, cpu_id) 3961076240SWill Deacon }; 407c0e8b0cSWill Deacon 417c0e8b0cSWill Deacon vcpu = calloc(1, sizeof(struct kvm_cpu)); 427c0e8b0cSWill Deacon if (!vcpu) 437c0e8b0cSWill Deacon return NULL; 447c0e8b0cSWill Deacon 457c0e8b0cSWill Deacon vcpu->vcpu_fd = ioctl(kvm->vm_fd, KVM_CREATE_VCPU, cpu_id); 467c0e8b0cSWill Deacon if (vcpu->vcpu_fd < 0) 477c0e8b0cSWill Deacon die_perror("KVM_CREATE_VCPU ioctl"); 487c0e8b0cSWill Deacon 497c0e8b0cSWill Deacon mmap_size = ioctl(kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0); 507c0e8b0cSWill Deacon if (mmap_size < 0) 517c0e8b0cSWill Deacon die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl"); 527c0e8b0cSWill Deacon 537c0e8b0cSWill Deacon vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED, 547c0e8b0cSWill Deacon vcpu->vcpu_fd, 0); 557c0e8b0cSWill Deacon if (vcpu->kvm_run == MAP_FAILED) 567c0e8b0cSWill Deacon die("unable to mmap vcpu fd"); 577c0e8b0cSWill Deacon 587c0e8b0cSWill Deacon /* Find an appropriate target CPU type. */ 597c0e8b0cSWill Deacon for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) { 608d0413d2SMarc Zyngier if (!kvm_arm_targets[i]) 618d0413d2SMarc Zyngier continue; 62*9b47146bSMarc Zyngier target = kvm_arm_targets[i]; 63*9b47146bSMarc Zyngier vcpu_init.target = target->id; 647c0e8b0cSWill Deacon err = ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init); 657c0e8b0cSWill Deacon if (!err) 667c0e8b0cSWill Deacon break; 677c0e8b0cSWill Deacon } 687c0e8b0cSWill Deacon 69*9b47146bSMarc Zyngier if (err || target->init(vcpu)) 707c0e8b0cSWill Deacon die("Unable to initialise ARM vcpu"); 717c0e8b0cSWill Deacon 727c0e8b0cSWill Deacon coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, 737c0e8b0cSWill Deacon KVM_CAP_COALESCED_MMIO); 747c0e8b0cSWill Deacon if (coalesced_offset) 757c0e8b0cSWill Deacon vcpu->ring = (void *)vcpu->kvm_run + 767c0e8b0cSWill Deacon (coalesced_offset * PAGE_SIZE); 777c0e8b0cSWill Deacon 787c0e8b0cSWill Deacon /* Populate the vcpu structure. */ 797c0e8b0cSWill Deacon vcpu->kvm = kvm; 807c0e8b0cSWill Deacon vcpu->cpu_id = cpu_id; 81*9b47146bSMarc Zyngier vcpu->cpu_type = target->id; 82*9b47146bSMarc Zyngier vcpu->cpu_compatible = target->compatible; 837c0e8b0cSWill Deacon vcpu->is_running = true; 847c0e8b0cSWill Deacon return vcpu; 857c0e8b0cSWill Deacon } 867c0e8b0cSWill Deacon 877c0e8b0cSWill Deacon void kvm_cpu__arch_nmi(struct kvm_cpu *cpu) 887c0e8b0cSWill Deacon { 897c0e8b0cSWill Deacon } 907c0e8b0cSWill Deacon 917c0e8b0cSWill Deacon void kvm_cpu__delete(struct kvm_cpu *vcpu) 927c0e8b0cSWill Deacon { 937c0e8b0cSWill Deacon free(vcpu); 947c0e8b0cSWill Deacon } 957c0e8b0cSWill Deacon 967c0e8b0cSWill Deacon bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu) 977c0e8b0cSWill Deacon { 987c0e8b0cSWill Deacon return false; 997c0e8b0cSWill Deacon } 1007c0e8b0cSWill Deacon 1017c0e8b0cSWill Deacon bool kvm_cpu__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, 1027c0e8b0cSWill Deacon u8 is_write) 1037c0e8b0cSWill Deacon { 1047c0e8b0cSWill Deacon if (arm_addr_in_virtio_mmio_region(phys_addr)) 1057c0e8b0cSWill Deacon return kvm__emulate_mmio(kvm, phys_addr, data, len, is_write); 1067c0e8b0cSWill Deacon else if (arm_addr_in_pci_mmio_region(phys_addr)) 1077c0e8b0cSWill Deacon die("PCI emulation not supported on ARM!"); 1087c0e8b0cSWill Deacon 1097c0e8b0cSWill Deacon return false; 1107c0e8b0cSWill Deacon } 1117c0e8b0cSWill Deacon 1127c0e8b0cSWill Deacon void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu) 1137c0e8b0cSWill Deacon { 1147c0e8b0cSWill Deacon } 115