xref: /kvmtool/kvm-cpu.c (revision 809f088b1d9fc4223c19a2f500e33adee5739ccc)
1 #include "kvm/kvm-cpu.h"
2 
3 #include "kvm/symbol.h"
4 #include "kvm/util.h"
5 #include "kvm/kvm.h"
6 
7 #include <sys/ioctl.h>
8 #include <sys/mman.h>
9 #include <signal.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <stdio.h>
14 
15 extern struct kvm_cpu **kvm_cpus;
16 extern __thread struct kvm_cpu *current_kvm_cpu;
17 
18 void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu)
19 {
20 	struct kvm_guest_debug debug = {
21 		.control	= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP,
22 	};
23 
24 	if (ioctl(vcpu->vcpu_fd, KVM_SET_GUEST_DEBUG, &debug) < 0)
25 		pr_warning("KVM_SET_GUEST_DEBUG failed");
26 }
27 
28 void kvm_cpu__run(struct kvm_cpu *vcpu)
29 {
30 	int err;
31 
32 	if (!vcpu->is_running)
33 		return;
34 
35 	err = ioctl(vcpu->vcpu_fd, KVM_RUN, 0);
36 	if (err < 0 && (errno != EINTR && errno != EAGAIN))
37 		die_perror("KVM_RUN failed");
38 }
39 
40 static void kvm_cpu_signal_handler(int signum)
41 {
42 	if (signum == SIGKVMEXIT) {
43 		if (current_kvm_cpu && current_kvm_cpu->is_running) {
44 			current_kvm_cpu->is_running = false;
45 			kvm__continue();
46 		}
47 	} else if (signum == SIGKVMPAUSE) {
48 		current_kvm_cpu->paused = 1;
49 	}
50 }
51 
52 static void kvm_cpu__handle_coalesced_mmio(struct kvm_cpu *cpu)
53 {
54 	if (cpu->ring) {
55 		while (cpu->ring->first != cpu->ring->last) {
56 			struct kvm_coalesced_mmio *m;
57 			m = &cpu->ring->coalesced_mmio[cpu->ring->first];
58 			kvm_cpu__emulate_mmio(cpu->kvm,
59 					      m->phys_addr,
60 					      m->data,
61 					      m->len,
62 					      1);
63 			cpu->ring->first = (cpu->ring->first + 1) % KVM_COALESCED_MMIO_MAX;
64 		}
65 	}
66 }
67 
68 void kvm_cpu__reboot(void)
69 {
70 	int i;
71 
72 	/* The kvm_cpus array contains a null pointer in the last location */
73 	for (i = 0; ; i++) {
74 		if (kvm_cpus[i])
75 			pthread_kill(kvm_cpus[i]->thread, SIGKVMEXIT);
76 		else
77 			break;
78 	}
79 }
80 
81 int kvm_cpu__start(struct kvm_cpu *cpu)
82 {
83 	sigset_t sigset;
84 
85 	sigemptyset(&sigset);
86 	sigaddset(&sigset, SIGALRM);
87 
88 	pthread_sigmask(SIG_BLOCK, &sigset, NULL);
89 
90 	signal(SIGKVMEXIT, kvm_cpu_signal_handler);
91 	signal(SIGKVMPAUSE, kvm_cpu_signal_handler);
92 
93 	kvm_cpu__reset_vcpu(cpu);
94 
95 	if (cpu->kvm->cfg.single_step)
96 		kvm_cpu__enable_singlestep(cpu);
97 
98 	while (cpu->is_running) {
99 		if (cpu->paused) {
100 			kvm__notify_paused();
101 			cpu->paused = 0;
102 		}
103 
104 		if (cpu->needs_nmi) {
105 			kvm_cpu__arch_nmi(cpu);
106 			cpu->needs_nmi = 0;
107 		}
108 
109 		kvm_cpu__run(cpu);
110 
111 		switch (cpu->kvm_run->exit_reason) {
112 		case KVM_EXIT_UNKNOWN:
113 			break;
114 		case KVM_EXIT_DEBUG:
115 			kvm_cpu__show_registers(cpu);
116 			kvm_cpu__show_code(cpu);
117 			break;
118 		case KVM_EXIT_IO: {
119 			bool ret;
120 
121 			ret = kvm_cpu__emulate_io(cpu->kvm,
122 						  cpu->kvm_run->io.port,
123 						  (u8 *)cpu->kvm_run +
124 						  cpu->kvm_run->io.data_offset,
125 						  cpu->kvm_run->io.direction,
126 						  cpu->kvm_run->io.size,
127 						  cpu->kvm_run->io.count);
128 
129 			if (!ret)
130 				goto panic_kvm;
131 			break;
132 		}
133 		case KVM_EXIT_MMIO: {
134 			bool ret;
135 
136 			/*
137 			 * If we had MMIO exit, coalesced ring should be processed
138 			 * *before* processing the exit itself
139 			 */
140 			kvm_cpu__handle_coalesced_mmio(cpu);
141 
142 			ret = kvm_cpu__emulate_mmio(cpu->kvm,
143 						    cpu->kvm_run->mmio.phys_addr,
144 						    cpu->kvm_run->mmio.data,
145 						    cpu->kvm_run->mmio.len,
146 						    cpu->kvm_run->mmio.is_write);
147 
148 			if (!ret)
149 				goto panic_kvm;
150 			break;
151 		}
152 		case KVM_EXIT_INTR:
153 			if (cpu->is_running)
154 				break;
155 			goto exit_kvm;
156 		case KVM_EXIT_SHUTDOWN:
157 			goto exit_kvm;
158 		default: {
159 			bool ret;
160 
161 			ret = kvm_cpu__handle_exit(cpu);
162 			if (!ret)
163 				goto panic_kvm;
164 			break;
165 		}
166 		}
167 		kvm_cpu__handle_coalesced_mmio(cpu);
168 	}
169 
170 exit_kvm:
171 	return 0;
172 
173 panic_kvm:
174 	return 1;
175 }
176