xref: /kvmtool/kvm-cpu.c (revision 2aa76b2616bcace1d668a879d834679dfa00dc8c)
1 #include "kvm/kvm-cpu.h"
2 
3 #include "kvm/symbol.h"
4 #include "kvm/util.h"
5 #include "kvm/kvm.h"
6 #include "kvm/virtio.h"
7 
8 #include <sys/ioctl.h>
9 #include <sys/mman.h>
10 #include <signal.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <stdio.h>
15 
16 extern __thread struct kvm_cpu *current_kvm_cpu;
17 
18 int __attribute__((weak)) kvm_cpu__get_endianness(struct kvm_cpu *vcpu)
19 {
20 	return VIRTIO_ENDIAN_HOST;
21 }
22 
23 void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu)
24 {
25 	struct kvm_guest_debug debug = {
26 		.control	= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP,
27 	};
28 
29 	if (ioctl(vcpu->vcpu_fd, KVM_SET_GUEST_DEBUG, &debug) < 0)
30 		pr_warning("KVM_SET_GUEST_DEBUG failed");
31 }
32 
33 void kvm_cpu__run(struct kvm_cpu *vcpu)
34 {
35 	int err;
36 
37 	if (!vcpu->is_running)
38 		return;
39 
40 	err = ioctl(vcpu->vcpu_fd, KVM_RUN, 0);
41 	if (err < 0 && (errno != EINTR && errno != EAGAIN))
42 		die_perror("KVM_RUN failed");
43 }
44 
45 static void kvm_cpu_signal_handler(int signum)
46 {
47 	if (signum == SIGKVMEXIT) {
48 		if (current_kvm_cpu && current_kvm_cpu->is_running)
49 			current_kvm_cpu->is_running = false;
50 	} else if (signum == SIGKVMPAUSE) {
51 		current_kvm_cpu->paused = 1;
52 	}
53 }
54 
55 static void kvm_cpu__handle_coalesced_mmio(struct kvm_cpu *cpu)
56 {
57 	if (cpu->ring) {
58 		while (cpu->ring->first != cpu->ring->last) {
59 			struct kvm_coalesced_mmio *m;
60 			m = &cpu->ring->coalesced_mmio[cpu->ring->first];
61 			kvm_cpu__emulate_mmio(cpu,
62 					      m->phys_addr,
63 					      m->data,
64 					      m->len,
65 					      1);
66 			cpu->ring->first = (cpu->ring->first + 1) % KVM_COALESCED_MMIO_MAX;
67 		}
68 	}
69 }
70 
71 int kvm_cpu__start(struct kvm_cpu *cpu)
72 {
73 	sigset_t sigset;
74 
75 	sigemptyset(&sigset);
76 	sigaddset(&sigset, SIGALRM);
77 
78 	pthread_sigmask(SIG_BLOCK, &sigset, NULL);
79 
80 	signal(SIGKVMEXIT, kvm_cpu_signal_handler);
81 	signal(SIGKVMPAUSE, kvm_cpu_signal_handler);
82 
83 	kvm_cpu__reset_vcpu(cpu);
84 
85 	if (cpu->kvm->cfg.single_step)
86 		kvm_cpu__enable_singlestep(cpu);
87 
88 	while (cpu->is_running) {
89 		if (cpu->paused) {
90 			kvm__notify_paused();
91 			cpu->paused = 0;
92 		}
93 
94 		if (cpu->needs_nmi) {
95 			kvm_cpu__arch_nmi(cpu);
96 			cpu->needs_nmi = 0;
97 		}
98 
99 		kvm_cpu__run(cpu);
100 
101 		switch (cpu->kvm_run->exit_reason) {
102 		case KVM_EXIT_UNKNOWN:
103 			break;
104 		case KVM_EXIT_DEBUG:
105 			kvm_cpu__show_registers(cpu);
106 			kvm_cpu__show_code(cpu);
107 			break;
108 		case KVM_EXIT_IO: {
109 			bool ret;
110 
111 			ret = kvm_cpu__emulate_io(cpu,
112 						  cpu->kvm_run->io.port,
113 						  (u8 *)cpu->kvm_run +
114 						  cpu->kvm_run->io.data_offset,
115 						  cpu->kvm_run->io.direction,
116 						  cpu->kvm_run->io.size,
117 						  cpu->kvm_run->io.count);
118 
119 			if (!ret)
120 				goto panic_kvm;
121 			break;
122 		}
123 		case KVM_EXIT_MMIO: {
124 			bool ret;
125 
126 			/*
127 			 * If we had MMIO exit, coalesced ring should be processed
128 			 * *before* processing the exit itself
129 			 */
130 			kvm_cpu__handle_coalesced_mmio(cpu);
131 
132 			ret = kvm_cpu__emulate_mmio(cpu,
133 						    cpu->kvm_run->mmio.phys_addr,
134 						    cpu->kvm_run->mmio.data,
135 						    cpu->kvm_run->mmio.len,
136 						    cpu->kvm_run->mmio.is_write);
137 
138 			if (!ret)
139 				goto panic_kvm;
140 			break;
141 		}
142 		case KVM_EXIT_INTR:
143 			if (cpu->is_running)
144 				break;
145 			goto exit_kvm;
146 		case KVM_EXIT_SHUTDOWN:
147 			goto exit_kvm;
148 		case KVM_EXIT_SYSTEM_EVENT:
149 			/*
150 			 * Print the type of system event and
151 			 * treat all system events as shutdown request.
152 			 */
153 			switch (cpu->kvm_run->system_event.type) {
154 			default:
155 				pr_warning("unknown system event type %d",
156 					   cpu->kvm_run->system_event.type);
157 				/* fall through for now */
158 			case KVM_SYSTEM_EVENT_RESET:
159 				/* Fall through for now */
160 			case KVM_SYSTEM_EVENT_SHUTDOWN:
161 				/*
162 				 * Ensure that all VCPUs are torn down,
163 				 * regardless of which CPU generated the event.
164 				 */
165 				kvm__reboot(cpu->kvm);
166 				goto exit_kvm;
167 			};
168 			break;
169 		default: {
170 			bool ret;
171 
172 			ret = kvm_cpu__handle_exit(cpu);
173 			if (!ret)
174 				goto panic_kvm;
175 			break;
176 		}
177 		}
178 		kvm_cpu__handle_coalesced_mmio(cpu);
179 	}
180 
181 exit_kvm:
182 	return 0;
183 
184 panic_kvm:
185 	return 1;
186 }
187 
188 int kvm_cpu__init(struct kvm *kvm)
189 {
190 	int max_cpus, recommended_cpus, i;
191 
192 	max_cpus = kvm__max_cpus(kvm);
193 	recommended_cpus = kvm__recommended_cpus(kvm);
194 
195 	if (kvm->cfg.nrcpus > max_cpus) {
196 		printf("  # Limit the number of CPUs to %d\n", max_cpus);
197 		kvm->cfg.nrcpus = max_cpus;
198 	} else if (kvm->cfg.nrcpus > recommended_cpus) {
199 		printf("  # Warning: The maximum recommended amount of VCPUs"
200 			" is %d\n", recommended_cpus);
201 	}
202 
203 	kvm->nrcpus = kvm->cfg.nrcpus;
204 
205 	/* Alloc one pointer too many, so array ends up 0-terminated */
206 	kvm->cpus = calloc(kvm->nrcpus + 1, sizeof(void *));
207 	if (!kvm->cpus) {
208 		pr_warning("Couldn't allocate array for %d CPUs", kvm->nrcpus);
209 		return -ENOMEM;
210 	}
211 
212 	for (i = 0; i < kvm->nrcpus; i++) {
213 		kvm->cpus[i] = kvm_cpu__arch_init(kvm, i);
214 		if (!kvm->cpus[i]) {
215 			pr_warning("unable to initialize KVM VCPU");
216 			goto fail_alloc;
217 		}
218 	}
219 
220 	return 0;
221 
222 fail_alloc:
223 	for (i = 0; i < kvm->nrcpus; i++)
224 		free(kvm->cpus[i]);
225 	return -ENOMEM;
226 }
227 base_init(kvm_cpu__init);
228 
229 int kvm_cpu__exit(struct kvm *kvm)
230 {
231 	int i, r;
232 	void *ret = NULL;
233 
234 	kvm_cpu__delete(kvm->cpus[0]);
235 	kvm->cpus[0] = NULL;
236 
237 	for (i = 1; i < kvm->nrcpus; i++) {
238 		if (kvm->cpus[i]->is_running) {
239 			pthread_kill(kvm->cpus[i]->thread, SIGKVMEXIT);
240 			if (pthread_join(kvm->cpus[i]->thread, &ret) != 0)
241 				die("pthread_join");
242 			kvm_cpu__delete(kvm->cpus[i]);
243 		}
244 		if (ret == NULL)
245 			r = 0;
246 	}
247 
248 	free(kvm->cpus);
249 
250 	kvm->nrcpus = 0;
251 
252 	return r;
253 }
254 core_exit(kvm_cpu__exit);
255