17c0e8b0cSWill Deacon #include "kvm/kvm.h"
27c0e8b0cSWill Deacon #include "kvm/kvm-cpu.h"
37c0e8b0cSWill Deacon
47c0e8b0cSWill Deacon static int debug_fd;
57c0e8b0cSWill Deacon
kvm_cpu__set_debug_fd(int fd)67c0e8b0cSWill Deacon void kvm_cpu__set_debug_fd(int fd)
77c0e8b0cSWill Deacon {
87c0e8b0cSWill Deacon debug_fd = fd;
97c0e8b0cSWill Deacon }
107c0e8b0cSWill Deacon
kvm_cpu__get_debug_fd(void)117c0e8b0cSWill Deacon int kvm_cpu__get_debug_fd(void)
127c0e8b0cSWill Deacon {
137c0e8b0cSWill Deacon return debug_fd;
147c0e8b0cSWill Deacon }
157c0e8b0cSWill Deacon
1685bd726aSAnup Patel static struct kvm_arm_target *kvm_arm_generic_target;
177c0e8b0cSWill Deacon static struct kvm_arm_target *kvm_arm_targets[KVM_ARM_NUM_TARGETS];
1885bd726aSAnup Patel
kvm_cpu__set_kvm_arm_generic_target(struct kvm_arm_target * target)1985bd726aSAnup Patel void kvm_cpu__set_kvm_arm_generic_target(struct kvm_arm_target *target)
2085bd726aSAnup Patel {
2185bd726aSAnup Patel kvm_arm_generic_target = target;
2285bd726aSAnup Patel }
2385bd726aSAnup Patel
kvm_cpu__register_kvm_arm_target(struct kvm_arm_target * target)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
kvm_cpu__arch_init(struct kvm * kvm,unsigned long cpu_id)387c0e8b0cSWill Deacon struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
397c0e8b0cSWill Deacon {
40*426e8752SJean-Philippe Brucker struct kvm_arm_target *target = NULL;
417c0e8b0cSWill Deacon struct kvm_cpu *vcpu;
427c0e8b0cSWill Deacon int coalesced_offset, mmap_size, err = -1;
437c0e8b0cSWill Deacon unsigned int i;
4485bd726aSAnup Patel struct kvm_vcpu_init preferred_init;
4561076240SWill Deacon struct kvm_vcpu_init vcpu_init = {
46b23aed2aSAlexandru Elisei .features = {},
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
66b23aed2aSAlexandru Elisei /* VCPU 0 is the boot CPU, the others start in a poweroff state. */
67b23aed2aSAlexandru Elisei if (cpu_id > 0)
68b23aed2aSAlexandru Elisei vcpu_init.features[0] |= (1UL << KVM_ARM_VCPU_POWER_OFF);
69b23aed2aSAlexandru Elisei
70c2dad402SAnup Patel /* Set KVM_ARM_VCPU_PSCI_0_2 if available */
71c2dad402SAnup Patel if (kvm__supports_extension(kvm, KVM_CAP_ARM_PSCI_0_2)) {
72c2dad402SAnup Patel vcpu_init.features[0] |= (1UL << KVM_ARM_VCPU_PSCI_0_2);
73c2dad402SAnup Patel }
74c2dad402SAnup Patel
7574c5e7b2SDave Martin kvm_cpu__select_features(kvm, &vcpu_init);
76254cb189SAmit Daniel Kachhap
7785bd726aSAnup Patel /*
7885bd726aSAnup Patel * If the preferred target ioctl is successful then
7985bd726aSAnup Patel * use preferred target else try each and every target type
8085bd726aSAnup Patel */
8185bd726aSAnup Patel err = ioctl(kvm->vm_fd, KVM_ARM_PREFERRED_TARGET, &preferred_init);
8285bd726aSAnup Patel if (!err) {
8385bd726aSAnup Patel /* Match preferred target CPU type. */
8485bd726aSAnup Patel for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) {
8585bd726aSAnup Patel if (!kvm_arm_targets[i])
8685bd726aSAnup Patel continue;
8785bd726aSAnup Patel if (kvm_arm_targets[i]->id == preferred_init.target) {
8885bd726aSAnup Patel target = kvm_arm_targets[i];
8985bd726aSAnup Patel break;
9085bd726aSAnup Patel }
9185bd726aSAnup Patel }
9285bd726aSAnup Patel if (!target) {
9385bd726aSAnup Patel target = kvm_arm_generic_target;
9485bd726aSAnup Patel vcpu_init.target = preferred_init.target;
9585bd726aSAnup Patel } else {
9685bd726aSAnup Patel vcpu_init.target = target->id;
9785bd726aSAnup Patel }
9885bd726aSAnup Patel err = ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init);
9985bd726aSAnup Patel } else {
1007c0e8b0cSWill Deacon /* Find an appropriate target CPU type. */
1017c0e8b0cSWill Deacon for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) {
1028d0413d2SMarc Zyngier if (!kvm_arm_targets[i])
1038d0413d2SMarc Zyngier continue;
1049b47146bSMarc Zyngier target = kvm_arm_targets[i];
1059b47146bSMarc Zyngier vcpu_init.target = target->id;
1067c0e8b0cSWill Deacon err = ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init);
1077c0e8b0cSWill Deacon if (!err)
1087c0e8b0cSWill Deacon break;
1097c0e8b0cSWill Deacon }
11085bd726aSAnup Patel if (err)
11185bd726aSAnup Patel die("Unable to find matching target");
11285bd726aSAnup Patel }
1137c0e8b0cSWill Deacon
114ff695820SSebastian Ene /* Populate the vcpu structure. */
115ff695820SSebastian Ene vcpu->kvm = kvm;
116ff695820SSebastian Ene vcpu->cpu_id = cpu_id;
117ff695820SSebastian Ene vcpu->cpu_type = vcpu_init.target;
118ff695820SSebastian Ene vcpu->cpu_compatible = target->compatible;
119ff695820SSebastian Ene vcpu->is_running = true;
120ff695820SSebastian Ene
1219b47146bSMarc Zyngier if (err || target->init(vcpu))
12285bd726aSAnup Patel die("Unable to initialise vcpu");
1237c0e8b0cSWill Deacon
1247c0e8b0cSWill Deacon coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION,
1257c0e8b0cSWill Deacon KVM_CAP_COALESCED_MMIO);
1267c0e8b0cSWill Deacon if (coalesced_offset)
1277c0e8b0cSWill Deacon vcpu->ring = (void *)vcpu->kvm_run +
1287c0e8b0cSWill Deacon (coalesced_offset * PAGE_SIZE);
1297c0e8b0cSWill Deacon
130a0eab49aSDave Martin if (kvm_cpu__configure_features(vcpu))
131a0eab49aSDave Martin die("Unable to configure requested vcpu features");
132a0eab49aSDave Martin
1337c0e8b0cSWill Deacon return vcpu;
1347c0e8b0cSWill Deacon }
1357c0e8b0cSWill Deacon
kvm_cpu__arch_nmi(struct kvm_cpu * cpu)1367c0e8b0cSWill Deacon void kvm_cpu__arch_nmi(struct kvm_cpu *cpu)
1377c0e8b0cSWill Deacon {
1387c0e8b0cSWill Deacon }
1397c0e8b0cSWill Deacon
kvm_cpu__delete(struct kvm_cpu * vcpu)1407c0e8b0cSWill Deacon void kvm_cpu__delete(struct kvm_cpu *vcpu)
1417c0e8b0cSWill Deacon {
1427d4671e5SSebastian Ene kvm_cpu__teardown_pvtime(vcpu->kvm);
1437c0e8b0cSWill Deacon free(vcpu);
1447c0e8b0cSWill Deacon }
1457c0e8b0cSWill Deacon
kvm_cpu__handle_exit(struct kvm_cpu * vcpu)1467c0e8b0cSWill Deacon bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
1477c0e8b0cSWill Deacon {
1487c0e8b0cSWill Deacon return false;
1497c0e8b0cSWill Deacon }
1507c0e8b0cSWill Deacon
kvm_cpu__show_page_tables(struct kvm_cpu * vcpu)1517c0e8b0cSWill Deacon void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
1527c0e8b0cSWill Deacon {
1537c0e8b0cSWill Deacon }
154