kvm-cpu.c 3.39 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "kvm/kvm.h"
#include "kvm/kvm-cpu.h"

static int debug_fd;

void kvm_cpu__set_debug_fd(int fd)
{
	debug_fd = fd;
}

int kvm_cpu__get_debug_fd(void)
{
	return debug_fd;
}

16
static struct kvm_arm_target *kvm_arm_generic_target;
17
static struct kvm_arm_target *kvm_arm_targets[KVM_ARM_NUM_TARGETS];
18
19
20
21
22
23

void kvm_cpu__set_kvm_arm_generic_target(struct kvm_arm_target *target)
{
	kvm_arm_generic_target = target;
}

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
int kvm_cpu__register_kvm_arm_target(struct kvm_arm_target *target)
{
	unsigned int i = 0;

	for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) {
		if (!kvm_arm_targets[i]) {
			kvm_arm_targets[i] = target;
			return 0;
		}
	}

	return -ENOSPC;
}

struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
{
40
	struct kvm_arm_target *target;
41
42
43
	struct kvm_cpu *vcpu;
	int coalesced_offset, mmap_size, err = -1;
	unsigned int i;
44
	struct kvm_vcpu_init preferred_init;
45
46
47
	struct kvm_vcpu_init vcpu_init = {
		.features = ARM_VCPU_FEATURE_FLAGS(kvm, cpu_id)
	};
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

	vcpu = calloc(1, sizeof(struct kvm_cpu));
	if (!vcpu)
		return NULL;

	vcpu->vcpu_fd = ioctl(kvm->vm_fd, KVM_CREATE_VCPU, cpu_id);
	if (vcpu->vcpu_fd < 0)
		die_perror("KVM_CREATE_VCPU ioctl");

	mmap_size = ioctl(kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
	if (mmap_size < 0)
		die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");

	vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED,
			     vcpu->vcpu_fd, 0);
	if (vcpu->kvm_run == MAP_FAILED)
		die("unable to mmap vcpu fd");

66
67
68
69
70
	/* Set KVM_ARM_VCPU_PSCI_0_2 if available */
	if (kvm__supports_extension(kvm, KVM_CAP_ARM_PSCI_0_2)) {
		vcpu_init.features[0] |= (1UL << KVM_ARM_VCPU_PSCI_0_2);
	}

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
	/*
	 * If the preferred target ioctl is successful then
	 * use preferred target else try each and every target type
	 */
	err = ioctl(kvm->vm_fd, KVM_ARM_PREFERRED_TARGET, &preferred_init);
	if (!err) {
		/* Match preferred target CPU type. */
		target = NULL;
		for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) {
			if (!kvm_arm_targets[i])
				continue;
			if (kvm_arm_targets[i]->id == preferred_init.target) {
				target = kvm_arm_targets[i];
				break;
			}
		}
		if (!target) {
			target = kvm_arm_generic_target;
			vcpu_init.target = preferred_init.target;
		} else {
			vcpu_init.target = target->id;
		}
93
		err = ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init);
94
95
96
97
98
99
100
101
102
103
104
105
106
	} else {
		/* Find an appropriate target CPU type. */
		for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) {
			if (!kvm_arm_targets[i])
				continue;
			target = kvm_arm_targets[i];
			vcpu_init.target = target->id;
			err = ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init);
			if (!err)
				break;
		}
		if (err)
			die("Unable to find matching target");
107
108
	}

109
	if (err || target->init(vcpu))
110
		die("Unable to initialise vcpu");
111
112
113
114
115
116
117
118
119
120

	coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION,
				 KVM_CAP_COALESCED_MMIO);
	if (coalesced_offset)
		vcpu->ring = (void *)vcpu->kvm_run +
			     (coalesced_offset * PAGE_SIZE);

	/* Populate the vcpu structure. */
	vcpu->kvm		= kvm;
	vcpu->cpu_id		= cpu_id;
121
	vcpu->cpu_type		= vcpu_init.target;
122
	vcpu->cpu_compatible	= target->compatible;
123
	vcpu->is_running	= true;
124

Dave Martin's avatar
Dave Martin committed
125
126
127
	if (kvm_cpu__configure_features(vcpu))
		die("Unable to configure requested vcpu features");

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
	return vcpu;
}

void kvm_cpu__arch_nmi(struct kvm_cpu *cpu)
{
}

void kvm_cpu__delete(struct kvm_cpu *vcpu)
{
	free(vcpu);
}

bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
{
	return false;
}

void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
{
}