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