xref: /kvmtool/arm/kvm-cpu.c (revision 7c0e8b0c5560ce2f500fa4d7ba7865e7360e7991)
1*7c0e8b0cSWill Deacon #include "kvm/kvm.h"
2*7c0e8b0cSWill Deacon #include "kvm/kvm-cpu.h"
3*7c0e8b0cSWill Deacon 
4*7c0e8b0cSWill Deacon static int debug_fd;
5*7c0e8b0cSWill Deacon 
6*7c0e8b0cSWill Deacon void kvm_cpu__set_debug_fd(int fd)
7*7c0e8b0cSWill Deacon {
8*7c0e8b0cSWill Deacon 	debug_fd = fd;
9*7c0e8b0cSWill Deacon }
10*7c0e8b0cSWill Deacon 
11*7c0e8b0cSWill Deacon int kvm_cpu__get_debug_fd(void)
12*7c0e8b0cSWill Deacon {
13*7c0e8b0cSWill Deacon 	return debug_fd;
14*7c0e8b0cSWill Deacon }
15*7c0e8b0cSWill Deacon 
16*7c0e8b0cSWill Deacon static struct kvm_arm_target *kvm_arm_targets[KVM_ARM_NUM_TARGETS];
17*7c0e8b0cSWill Deacon int kvm_cpu__register_kvm_arm_target(struct kvm_arm_target *target)
18*7c0e8b0cSWill Deacon {
19*7c0e8b0cSWill Deacon 	unsigned int i = 0;
20*7c0e8b0cSWill Deacon 
21*7c0e8b0cSWill Deacon 	for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) {
22*7c0e8b0cSWill Deacon 		if (!kvm_arm_targets[i]) {
23*7c0e8b0cSWill Deacon 			kvm_arm_targets[i] = target;
24*7c0e8b0cSWill Deacon 			return 0;
25*7c0e8b0cSWill Deacon 		}
26*7c0e8b0cSWill Deacon 	}
27*7c0e8b0cSWill Deacon 
28*7c0e8b0cSWill Deacon 	return -ENOSPC;
29*7c0e8b0cSWill Deacon }
30*7c0e8b0cSWill Deacon 
31*7c0e8b0cSWill Deacon struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
32*7c0e8b0cSWill Deacon {
33*7c0e8b0cSWill Deacon 	struct kvm_cpu *vcpu;
34*7c0e8b0cSWill Deacon 	int coalesced_offset, mmap_size, err = -1;
35*7c0e8b0cSWill Deacon 	unsigned int i;
36*7c0e8b0cSWill Deacon 	struct kvm_vcpu_init vcpu_init = { };
37*7c0e8b0cSWill Deacon 
38*7c0e8b0cSWill Deacon 	vcpu = calloc(1, sizeof(struct kvm_cpu));
39*7c0e8b0cSWill Deacon 	if (!vcpu)
40*7c0e8b0cSWill Deacon 		return NULL;
41*7c0e8b0cSWill Deacon 
42*7c0e8b0cSWill Deacon 	vcpu->vcpu_fd = ioctl(kvm->vm_fd, KVM_CREATE_VCPU, cpu_id);
43*7c0e8b0cSWill Deacon 	if (vcpu->vcpu_fd < 0)
44*7c0e8b0cSWill Deacon 		die_perror("KVM_CREATE_VCPU ioctl");
45*7c0e8b0cSWill Deacon 
46*7c0e8b0cSWill Deacon 	mmap_size = ioctl(kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
47*7c0e8b0cSWill Deacon 	if (mmap_size < 0)
48*7c0e8b0cSWill Deacon 		die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
49*7c0e8b0cSWill Deacon 
50*7c0e8b0cSWill Deacon 	vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED,
51*7c0e8b0cSWill Deacon 			     vcpu->vcpu_fd, 0);
52*7c0e8b0cSWill Deacon 	if (vcpu->kvm_run == MAP_FAILED)
53*7c0e8b0cSWill Deacon 		die("unable to mmap vcpu fd");
54*7c0e8b0cSWill Deacon 
55*7c0e8b0cSWill Deacon 	/* Find an appropriate target CPU type. */
56*7c0e8b0cSWill Deacon 	for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) {
57*7c0e8b0cSWill Deacon 		vcpu_init.target = kvm_arm_targets[i]->id;
58*7c0e8b0cSWill Deacon 		err = ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init);
59*7c0e8b0cSWill Deacon 		if (!err)
60*7c0e8b0cSWill Deacon 			break;
61*7c0e8b0cSWill Deacon 	}
62*7c0e8b0cSWill Deacon 
63*7c0e8b0cSWill Deacon 	if (err || kvm_arm_targets[i]->init(vcpu))
64*7c0e8b0cSWill Deacon 		die("Unable to initialise ARM vcpu");
65*7c0e8b0cSWill Deacon 
66*7c0e8b0cSWill Deacon 	coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION,
67*7c0e8b0cSWill Deacon 				 KVM_CAP_COALESCED_MMIO);
68*7c0e8b0cSWill Deacon 	if (coalesced_offset)
69*7c0e8b0cSWill Deacon 		vcpu->ring = (void *)vcpu->kvm_run +
70*7c0e8b0cSWill Deacon 			     (coalesced_offset * PAGE_SIZE);
71*7c0e8b0cSWill Deacon 
72*7c0e8b0cSWill Deacon 	/* Populate the vcpu structure. */
73*7c0e8b0cSWill Deacon 	vcpu->kvm		= kvm;
74*7c0e8b0cSWill Deacon 	vcpu->cpu_id		= cpu_id;
75*7c0e8b0cSWill Deacon 	vcpu->cpu_type		= vcpu_init.target;
76*7c0e8b0cSWill Deacon 	vcpu->is_running	= true;
77*7c0e8b0cSWill Deacon 	return vcpu;
78*7c0e8b0cSWill Deacon }
79*7c0e8b0cSWill Deacon 
80*7c0e8b0cSWill Deacon void kvm_cpu__arch_nmi(struct kvm_cpu *cpu)
81*7c0e8b0cSWill Deacon {
82*7c0e8b0cSWill Deacon }
83*7c0e8b0cSWill Deacon 
84*7c0e8b0cSWill Deacon void kvm_cpu__delete(struct kvm_cpu *vcpu)
85*7c0e8b0cSWill Deacon {
86*7c0e8b0cSWill Deacon 	free(vcpu);
87*7c0e8b0cSWill Deacon }
88*7c0e8b0cSWill Deacon 
89*7c0e8b0cSWill Deacon bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
90*7c0e8b0cSWill Deacon {
91*7c0e8b0cSWill Deacon 	return false;
92*7c0e8b0cSWill Deacon }
93*7c0e8b0cSWill Deacon 
94*7c0e8b0cSWill Deacon bool kvm_cpu__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len,
95*7c0e8b0cSWill Deacon 			   u8 is_write)
96*7c0e8b0cSWill Deacon {
97*7c0e8b0cSWill Deacon 	if (arm_addr_in_virtio_mmio_region(phys_addr))
98*7c0e8b0cSWill Deacon 		return kvm__emulate_mmio(kvm, phys_addr, data, len, is_write);
99*7c0e8b0cSWill Deacon 	else if (arm_addr_in_pci_mmio_region(phys_addr))
100*7c0e8b0cSWill Deacon 		die("PCI emulation not supported on ARM!");
101*7c0e8b0cSWill Deacon 
102*7c0e8b0cSWill Deacon 	return false;
103*7c0e8b0cSWill Deacon }
104*7c0e8b0cSWill Deacon 
105*7c0e8b0cSWill Deacon void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
106*7c0e8b0cSWill Deacon {
107*7c0e8b0cSWill Deacon }
108