kvm: user: ppc: fix build break caused by changes to kvm_callbacks
[qemu-kvm/fedora.git] / kvm / user / main-ppc.c
blob5fdf28e0a6fcc3f6f5d2b9f9649d767cf115c69f
1 /*
2 * Kernel-based Virtual Machine test driver
4 * This test driver provides a simple way of testing kvm, without a full
5 * device model.
7 * Copyright (C) 2006 Qumranet
8 * Copyright IBM Corp. 2008
10 * Authors:
12 * Avi Kivity <avi@qumranet.com>
13 * Yaniv Kamay <yaniv@qumranet.com>
14 * Hollis Blanchard <hollisb@us.ibm.com>
16 * This work is licensed under the GNU LGPL license, version 2.
19 #define _GNU_SOURCE
21 #include <libkvm.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <semaphore.h>
29 #include <sys/types.h>
30 #include <errno.h>
31 #include <pthread.h>
32 #include <signal.h>
33 #include <pthread.h>
34 #include <sys/syscall.h>
35 #include <linux/unistd.h>
36 #include <getopt.h>
37 #include <stdbool.h>
38 #include <inttypes.h>
40 #include "iotable.h"
42 static int gettid(void)
44 return syscall(__NR_gettid);
47 kvm_context_t kvm;
49 #define IPI_SIGNAL (SIGRTMIN + 4)
51 struct io_table mmio_table;
53 static int ncpus = 1;
54 static sem_t exited_sem;
55 static __thread int vcpu;
56 static sigset_t kernel_sigmask;
57 static sigset_t ipi_sigmask;
58 static uint64_t memory_size = 128 * 1024 * 1024;
60 struct vcpu_info {
61 pid_t tid;
64 struct vcpu_info *vcpus;
66 static int test_debug(void *opaque, void *vcpu)
68 printf("test_debug\n");
69 return 0;
72 static int test_halt(void *opaque, int vcpu)
74 int n;
76 sigwait(&ipi_sigmask, &n);
77 return 0;
80 static int test_io_window(void *opaque)
82 return 0;
85 static int test_try_push_interrupts(void *opaque)
87 return 0;
90 static void test_push_nmi(void *opaque)
94 static void test_post_kvm_run(void *opaque, void *vcpu)
98 static int test_pre_kvm_run(void *opaque, void *vcpu)
100 return 0;
103 static int mmio_handler(void *opaque, int len, int is_write, uint64_t offset,
104 uint64_t *data)
106 int r = 0;
108 switch (offset) {
109 case 0: /* putc */
110 putc(*(char *)data, stdout);
111 fflush(stdout);
112 break;
113 case 1: /* exit */
114 r = *(char *)data;
115 break;
116 default:
117 printf("%s: offset %"PRIx64" len %d data %"PRIx64"\n",
118 __func__, offset, len, *(uint64_t *)data);
119 r = -EINVAL;
122 return r;
125 static int test_mem_read(void *opaque, uint64_t addr, uint8_t *data, int len)
127 struct io_table_entry *iodev;
129 #if 0
130 printf("%s: addr %"PRIx64" len %d\n", __func__, addr, len);
131 #endif
133 iodev = io_table_lookup(&mmio_table, addr);
134 if (!iodev) {
135 printf("couldn't find device\n");
136 return -ENODEV;
139 return iodev->handler(iodev->opaque, len, 0, addr - iodev->start,
140 (uint64_t *)data);
143 static int test_mem_write(void *opaque, uint64_t addr, uint8_t *data, int len)
145 struct io_table_entry *iodev;
147 #if 0
148 printf("%s: addr %"PRIx64" len %d data %"PRIx64"\n",
149 __func__, addr, len, *(uint64_t *)data);
150 #endif
152 iodev = io_table_lookup(&mmio_table, addr);
153 if (!iodev) {
154 printf("couldn't find device\n");
155 return -ENODEV;
158 return iodev->handler(iodev->opaque, len, 1, addr - iodev->start,
159 (uint64_t *)data);
162 static int test_dcr_read(int vcpu, uint32_t dcrn, uint32_t *data)
164 printf("%s: dcrn %04X\n", __func__, dcrn);
165 *data = 0;
166 return 0;
169 static int test_dcr_write(int vcpu, uint32_t dcrn, uint32_t data)
171 printf("%s: dcrn %04X data %04X\n", __func__, dcrn, data);
172 return 0;
175 static struct kvm_callbacks test_callbacks = {
176 .mmio_read = test_mem_read,
177 .mmio_write = test_mem_write,
178 .debug = test_debug,
179 .halt = test_halt,
180 .io_window = test_io_window,
181 .try_push_interrupts = test_try_push_interrupts,
182 .push_nmi = test_push_nmi,
183 .post_kvm_run = test_post_kvm_run,
184 .pre_kvm_run = test_pre_kvm_run,
185 .powerpc_dcr_read = test_dcr_read,
186 .powerpc_dcr_write = test_dcr_write,
189 static unsigned long load_file(void *mem, const char *fname, int inval_icache)
191 ssize_t r;
192 int fd;
193 unsigned long bytes = 0;
195 fd = open(fname, O_RDONLY);
196 if (fd == -1) {
197 perror("open");
198 exit(1);
201 while ((r = read(fd, mem, 4096)) != -1 && r != 0) {
202 mem += r;
203 bytes += r;
206 if (r == -1) {
207 perror("read");
208 printf("read %d bytes\n", bytes);
209 exit(1);
212 return bytes;
215 #define ICACHE_LINE_SIZE 32
217 void sync_caches(void *mem, unsigned long len)
219 unsigned long i;
221 for (i = 0; i < len; i += ICACHE_LINE_SIZE)
222 asm volatile ("dcbst %0, %1" : : "g"(mem), "r"(i));
223 asm volatile ("sync");
224 for (i = 0; i < len; i += ICACHE_LINE_SIZE)
225 asm volatile ("icbi %0, %1" : : "g"(mem), "r"(i));
226 asm volatile ("sync; isync");
229 static void init_vcpu(int n)
231 sigemptyset(&ipi_sigmask);
232 sigaddset(&ipi_sigmask, IPI_SIGNAL);
233 sigprocmask(SIG_UNBLOCK, &ipi_sigmask, NULL);
234 sigprocmask(SIG_BLOCK, &ipi_sigmask, &kernel_sigmask);
235 vcpus[n].tid = gettid();
236 vcpu = n;
237 kvm_set_signal_mask(kvm, n, &kernel_sigmask);
240 static void *do_create_vcpu(void *_n)
242 int n = (long)_n;
244 kvm_create_vcpu(kvm, n);
245 init_vcpu(n);
246 kvm_run(kvm, n, &vcpus[n]);
247 sem_post(&exited_sem);
248 return NULL;
251 static void start_vcpu(int n)
253 pthread_t thread;
255 pthread_create(&thread, NULL, do_create_vcpu, (void *)(long)n);
258 static void usage(const char *progname)
260 fprintf(stderr,
261 "Usage: %s [OPTIONS] [bootstrap] flatfile\n"
262 "KVM test harness.\n"
263 "\n"
264 " -s, --smp=NUM create a VM with NUM virtual CPUs\n"
265 " -m, --memory=NUM[GMKB] allocate NUM memory for virtual machine. A suffix\n"
266 " can be used to change the unit (default: `M')\n"
267 " -h, --help display this help screen and exit\n"
268 "\n"
269 "Report bugs to <kvm-devel@lists.sourceforge.net>.\n"
270 , progname);
273 static void sig_ignore(int sig)
275 write(1, "boo\n", 4);
278 int main(int argc, char **argv)
280 void *vm_mem;
281 unsigned long len;
282 int i;
283 const char *sopts = "s:phm:";
284 struct option lopts[] = {
285 { "smp", 1, 0, 's' },
286 { "memory", 1, 0, 'm' },
287 { "help", 0, 0, 'h' },
288 { 0 },
290 int opt_ind, ch;
291 int nb_args;
292 char *endptr;
294 while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) {
295 switch (ch) {
296 case 's':
297 ncpus = atoi(optarg);
298 break;
299 case 'm':
300 memory_size = strtoull(optarg, &endptr, 0);
301 switch (*endptr) {
302 case 'G': case 'g':
303 memory_size <<= 30;
304 break;
305 case '\0':
306 case 'M': case 'm':
307 memory_size <<= 20;
308 break;
309 case 'K': case 'k':
310 memory_size <<= 10;
311 break;
312 default:
313 fprintf(stderr,
314 "Unrecongized memory suffix: %c\n",
315 *endptr);
316 exit(1);
318 if (memory_size == 0) {
319 fprintf(stderr,
320 "Invalid memory size: 0\n");
321 exit(1);
323 break;
324 case 'h':
325 usage(argv[0]);
326 exit(0);
327 case '?':
328 default:
329 fprintf(stderr,
330 "Try `%s --help' for more information.\n",
331 argv[0]);
332 exit(1);
336 nb_args = argc - optind;
337 if (nb_args < 1 || nb_args > 2) {
338 fprintf(stderr,
339 "Incorrect number of arguments.\n"
340 "Try `%s --help' for more information.\n",
341 argv[0]);
342 exit(1);
345 signal(IPI_SIGNAL, sig_ignore);
347 vcpus = calloc(ncpus, sizeof *vcpus);
348 if (!vcpus) {
349 fprintf(stderr, "calloc failed\n");
350 return 1;
353 kvm = kvm_init(&test_callbacks, 0);
354 if (!kvm) {
355 fprintf(stderr, "kvm_init failed\n");
356 return 1;
358 if (kvm_create(kvm, memory_size, &vm_mem) < 0) {
359 kvm_finalize(kvm);
360 fprintf(stderr, "kvm_create failed\n");
361 return 1;
364 vm_mem = kvm_create_phys_mem(kvm, 0, memory_size, 0, 1);
366 len = load_file(vm_mem, argv[optind], 1);
367 sync_caches(vm_mem, len);
369 io_table_register(&mmio_table, 0xf0000000, 64, mmio_handler, NULL);
371 sem_init(&exited_sem, 0, 0);
372 for (i = 0; i < ncpus; ++i)
373 start_vcpu(i);
374 /* Wait for all vcpus to exit. */
375 for (i = 0; i < ncpus; ++i)
376 sem_wait(&exited_sem);
378 return 0;