xref: /kvmtool/arm/kvm-cpu.c (revision 9b47146bc9a1ff1a08d6e2e2f9cb517e075dd662)
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