]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - tools/kvm/kvm.c
kvm: Use 64 bit names when showing registers
[karo-tx-linux.git] / tools / kvm / kvm.c
1 #include "kvm/kvm.h"
2
3 #include <linux/kvm.h>
4
5 #include <asm/bootparam.h>
6
7 #include <sys/ioctl.h>
8 #include <inttypes.h>
9 #include <sys/mman.h>
10 #include <stdbool.h>
11 #include <limits.h>
12 #include <stdarg.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <stdio.h>
17 #include <fcntl.h>
18
19 #include "util.h"
20
21 /*
22  * Compatibility code. Remove this when we move to tools/kvm.
23  */
24 #ifndef KVM_EXIT_INTERNAL_ERROR
25 # define KVM_EXIT_INTERNAL_ERROR                17
26 #endif
27
28 #define DEFINE_KVM_EXIT_REASON(reason) [reason] = #reason
29
30 const char *kvm_exit_reasons[] = {
31         DEFINE_KVM_EXIT_REASON(KVM_EXIT_UNKNOWN),
32         DEFINE_KVM_EXIT_REASON(KVM_EXIT_EXCEPTION),
33         DEFINE_KVM_EXIT_REASON(KVM_EXIT_IO),
34         DEFINE_KVM_EXIT_REASON(KVM_EXIT_HYPERCALL),
35         DEFINE_KVM_EXIT_REASON(KVM_EXIT_DEBUG),
36         DEFINE_KVM_EXIT_REASON(KVM_EXIT_HLT),
37         DEFINE_KVM_EXIT_REASON(KVM_EXIT_MMIO),
38         DEFINE_KVM_EXIT_REASON(KVM_EXIT_IRQ_WINDOW_OPEN),
39         DEFINE_KVM_EXIT_REASON(KVM_EXIT_SHUTDOWN),
40         DEFINE_KVM_EXIT_REASON(KVM_EXIT_FAIL_ENTRY),
41         DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTR),
42         DEFINE_KVM_EXIT_REASON(KVM_EXIT_SET_TPR),
43         DEFINE_KVM_EXIT_REASON(KVM_EXIT_TPR_ACCESS),
44         DEFINE_KVM_EXIT_REASON(KVM_EXIT_S390_SIEIC),
45         DEFINE_KVM_EXIT_REASON(KVM_EXIT_S390_RESET),
46         DEFINE_KVM_EXIT_REASON(KVM_EXIT_DCR),
47         DEFINE_KVM_EXIT_REASON(KVM_EXIT_NMI),
48         DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTERNAL_ERROR),
49 };
50
51 static inline uint32_t segment_to_flat(uint16_t selector, uint16_t offset)
52 {
53         return ((uint32_t)selector << 4) + (uint32_t) offset;
54 }
55
56 static inline void *guest_flat_to_host(struct kvm *self, unsigned long offset)
57 {
58         return self->ram_start + offset;
59 }
60
61 static inline void *guest_real_to_host(struct kvm *self, uint16_t selector, uint16_t offset)
62 {
63         unsigned long flat = segment_to_flat(selector, offset);
64
65         return guest_flat_to_host(self, flat);
66 }
67
68 static bool kvm__supports_extension(struct kvm *self, unsigned int extension)
69 {
70         int ret;
71
72         ret = ioctl(self->sys_fd, KVM_CHECK_EXTENSION, extension);
73         if (ret < 0)
74                 return false;
75
76         return ret;
77 }
78
79 static struct kvm *kvm__new(void)
80 {
81         struct kvm *self = calloc(1, sizeof *self);
82
83         if (!self)
84                 die("out of memory");
85
86         return self;
87 }
88
89 struct kvm *kvm__init(void)
90 {
91         struct kvm_userspace_memory_region mem;
92         struct kvm *self;
93         long page_size;
94         int mmap_size;
95         int ret;
96
97         self = kvm__new();
98
99         self->sys_fd = open("/dev/kvm", O_RDWR);
100         if (self->sys_fd < 0)
101                 die_perror("open");
102
103         ret = ioctl(self->sys_fd, KVM_GET_API_VERSION, 0);
104         if (ret != KVM_API_VERSION)
105                 die_perror("KVM_API_VERSION ioctl");
106
107         self->vm_fd = ioctl(self->sys_fd, KVM_CREATE_VM, 0);
108         if (self->vm_fd < 0)
109                 die_perror("KVM_CREATE_VM ioctl");
110
111         if (!kvm__supports_extension(self, KVM_CAP_USER_MEMORY))
112                 die("KVM_CAP_USER_MEMORY is not supported");
113
114         self->ram_size          = 64UL * 1024UL * 1024UL;
115
116         page_size       = sysconf(_SC_PAGESIZE);
117         if (posix_memalign(&self->ram_start, page_size, self->ram_size) != 0)
118                 die("out of memory");
119
120         mem = (struct kvm_userspace_memory_region) {
121                 .slot                   = 0,
122                 .guest_phys_addr        = 0x0UL,
123                 .memory_size            = self->ram_size,
124                 .userspace_addr         = (unsigned long) self->ram_start,
125         };
126
127         ret = ioctl(self->vm_fd, KVM_SET_USER_MEMORY_REGION, &mem, 1);
128         if (ret < 0)
129                 die_perror("KVM_SET_USER_MEMORY_REGION ioctl");
130
131         if (!kvm__supports_extension(self, KVM_CAP_SET_TSS_ADDR))
132                 die("KVM_CAP_SET_TSS_ADDR is not supported");
133
134         ret = ioctl(self->vm_fd, KVM_SET_TSS_ADDR, 0xfffbd000);
135         if (ret < 0)
136                 die_perror("KVM_SET_TSS_ADDR ioctl");
137
138         self->vcpu_fd = ioctl(self->vm_fd, KVM_CREATE_VCPU, 0);
139         if (self->vcpu_fd < 0)
140                 die_perror("KVM_CREATE_VCPU ioctl");
141
142         mmap_size = ioctl(self->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
143         if (mmap_size < 0)
144                 die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
145
146         self->kvm_run = mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, self->vcpu_fd, 0);
147         if (self->kvm_run == MAP_FAILED)
148                 die("unable to mmap vcpu fd");
149
150         return self;
151 }
152
153 void kvm__enable_singlestep(struct kvm *self)
154 {
155         struct kvm_guest_debug debug = {
156                 .control        = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP,
157         };
158
159         if (ioctl(self->vcpu_fd, KVM_SET_GUEST_DEBUG, &debug) < 0)
160                 warning("KVM_SET_GUEST_DEBUG failed");
161 }
162
163 #define BOOT_LOADER_SELECTOR    0x0100
164 #define BOOT_LOADER_IP          0x0000
165 #define BOOT_LOADER_SP          0x8000
166
167 static int load_flat_binary(struct kvm *self, int fd)
168 {
169         void *p;
170         int nr;
171
172         if (lseek(fd, 0, SEEK_SET) < 0)
173                 die_perror("lseek");
174
175         p = guest_real_to_host(self, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
176
177         while ((nr = read(fd, p, 65536)) > 0)
178                 p += nr;
179
180         self->boot_selector     = BOOT_LOADER_SELECTOR;
181         self->boot_ip           = BOOT_LOADER_IP;
182         self->boot_sp           = BOOT_LOADER_SP;
183
184         return true;
185 }
186
187 /*
188  * The protected mode kernel part of a modern bzImage is loaded at 1 MB by
189  * default.
190  */
191 #define BZ_KERNEL_START                 0x100000UL
192
193 static const char *BZIMAGE_MAGIC        = "HdrS";
194
195 #define BZ_DEFAULT_SETUP_SECTS          4
196
197 static bool load_bzimage(struct kvm *self, int fd)
198 {
199         unsigned long setup_sects;
200         struct boot_params boot;
201         ssize_t setup_size;
202         void *p;
203         int nr;
204
205         /*
206          * See Documentation/x86/boot.txt for details no bzImage on-disk and
207          * memory layout.
208          */
209
210         if (lseek(fd, 0, SEEK_SET) < 0)
211                 die_perror("lseek");
212
213         read(fd, &boot, sizeof(boot));
214
215         if (memcmp(&boot.hdr.header, BZIMAGE_MAGIC, strlen(BZIMAGE_MAGIC)) != 0)
216                 return false;
217
218         if (lseek(fd, 0, SEEK_SET) < 0)
219                 die_perror("lseek");
220
221         if (!boot.hdr.setup_sects)
222                 boot.hdr.setup_sects = BZ_DEFAULT_SETUP_SECTS;
223         setup_sects = boot.hdr.setup_sects + 1;
224
225         setup_size = setup_sects << 9;
226         p = guest_real_to_host(self, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
227
228         if (read(fd, p, setup_size) != setup_size)
229                 die_perror("read");
230
231         p = guest_flat_to_host(self, BZ_KERNEL_START);
232
233         while ((nr = read(fd, p, 65536)) > 0)
234                 p += nr;
235
236         self->boot_selector     = BOOT_LOADER_SELECTOR;
237         /*
238          * The real-mode setup code starts at offset 0x200 of a bzImage. See
239          * Documentation/x86/boot.txt for details.
240          */
241         self->boot_ip           = BOOT_LOADER_IP + 0x200;
242         self->boot_sp           = BOOT_LOADER_SP;
243
244         return true;
245 }
246
247 bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename)
248 {
249         bool ret;
250         int fd;
251
252         fd = open(kernel_filename, O_RDONLY);
253         if (fd < 0)
254                 die("unable to open kernel");
255
256         ret = load_bzimage(kvm, fd);
257         if (ret)
258                 goto found_kernel;
259
260         ret = load_flat_binary(kvm, fd);
261         if (ret)
262                 goto found_kernel;
263
264         die("%s is not a valid bzImage or flat binary", kernel_filename);
265
266 found_kernel:
267         return ret;
268 }
269
270 static inline uint64_t ip_flat_to_real(struct kvm *self, uint64_t ip)
271 {
272         uint64_t cs = self->sregs.cs.selector;
273
274         return ip - (cs << 4);
275 }
276
277 static inline uint64_t ip_real_to_flat(struct kvm *self, uint64_t ip)
278 {
279         uint64_t cs = self->sregs.cs.selector;
280
281         return ip + (cs << 4);
282 }
283
284 static inline uint32_t selector_to_base(uint16_t selector)
285 {
286         /*
287          * KVM on Intel requires 'base' to be 'selector * 16' in real mode.
288          */
289         return (uint32_t)selector * 16;
290 }
291
292 void kvm__reset_vcpu(struct kvm *self)
293 {
294         self->sregs = (struct kvm_sregs) {
295                 .cr0            = 0x60000010ULL,
296                 .cs             = (struct kvm_segment) {
297                         .selector       = self->boot_selector,
298                         .base           = selector_to_base(self->boot_selector),
299                         .limit          = 0xffffU,
300                         .type           = 0x0bU,
301                         .present        = 1,
302                         .dpl            = 0x03,
303                         .s              = 1,
304                 },
305                 .ss             = (struct kvm_segment) {
306                         .selector       = self->boot_selector,
307                         .base           = selector_to_base(self->boot_selector),
308                         .limit          = 0xffffU,
309                         .type           = 0x03U,
310                         .present        = 1,
311                         .dpl            = 0x03,
312                         .s              = 1,
313                 },
314                 .ds             = (struct kvm_segment) {
315                         .selector       = self->boot_selector,
316                         .base           = selector_to_base(self->boot_selector),
317                         .limit          = 0xffffU,
318                         .type           = 0x03U,
319                         .present        = 1,
320                         .dpl            = 0x03,
321                         .s              = 1,
322                 },
323                 .es             = (struct kvm_segment) {
324                         .selector       = self->boot_selector,
325                         .base           = selector_to_base(self->boot_selector),
326                         .limit          = 0xffffU,
327                         .type           = 0x03U,
328                         .present        = 1,
329                         .dpl            = 0x03,
330                         .s              = 1,
331                 },
332                 .fs             = (struct kvm_segment) {
333                         .selector       = self->boot_selector,
334                         .base           = selector_to_base(self->boot_selector),
335                         .limit          = 0xffffU,
336                         .type           = 0x03U,
337                         .present        = 1,
338                         .dpl            = 0x03,
339                         .s              = 1,
340                 },
341                 .gs             = (struct kvm_segment) {
342                         .selector       = self->boot_selector,
343                         .base           = selector_to_base(self->boot_selector),
344                         .limit          = 0xffffU,
345                         .type           = 0x03U,
346                         .present        = 1,
347                         .dpl            = 0x03,
348                         .s              = 1,
349                 },
350                 .tr             = (struct kvm_segment) {
351                         .limit          = 0xffffU,
352                         .present        = 1,
353                         .type           = 0x03U,
354                 },
355                 .ldt            = (struct kvm_segment) {
356                         .limit          = 0xffffU,
357                         .present        = 1,
358                         .type           = 0x02U,
359                 },
360                 .gdt            = (struct kvm_dtable) {
361                         .limit          = 0xffffU,
362                 },
363                 .idt            = (struct kvm_dtable) {
364                         .limit          = 0xffffU,
365                 },
366         };
367
368         if (ioctl(self->vcpu_fd, KVM_SET_SREGS, &self->sregs) < 0)
369                 die_perror("KVM_SET_SREGS failed");
370
371         self->regs = (struct kvm_regs) {
372                 /* We start the guest in 16-bit real mode  */
373                 .rflags         = 0x0000000000000002ULL,
374
375                 .rip            = self->boot_ip,
376                 .rsp            = self->boot_sp,
377                 .rbp            = self->boot_sp,
378         };
379
380         if (self->regs.rip > USHRT_MAX)
381                 die("ip 0x%" PRIx64 " is too high for real mode", (uint64_t) self->regs.rip);
382
383         if (ioctl(self->vcpu_fd, KVM_SET_REGS, &self->regs) < 0)
384                 die_perror("KVM_SET_REGS failed");
385
386 }
387
388 void kvm__run(struct kvm *self)
389 {
390         if (ioctl(self->vcpu_fd, KVM_RUN, 0) < 0)
391                 die_perror("KVM_RUN failed");
392 }
393
394 static void kvm__emulate_io_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
395 {
396         fprintf(stderr, "%s port=%x, size=%d, count=%" PRIu32 "\n", __func__, port, size, count);
397 }
398
399 static void kvm__emulate_io_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
400 {
401         fprintf(stderr, "%s port=%x, size=%d, count=%" PRIu32 "\n", __func__, port, size, count);
402 }
403
404 void kvm__emulate_io(struct kvm *self, uint16_t port, void *data, int direction, int size, uint32_t count)
405 {
406         if (direction == KVM_EXIT_IO_IN)
407                 kvm__emulate_io_in(self, port, data, size, count);
408         else
409                 kvm__emulate_io_out(self, port, data, size, count);
410 }
411
412 static void print_segment(const char *name, struct kvm_segment *seg)
413 {
414         printf(" %s       %04" PRIx16 "      %016" PRIx64 "  %08" PRIx32 "  %02" PRIx8 "    %x %x   %x  %x %x %x %x\n",
415                 name, (uint16_t) seg->selector, (uint64_t) seg->base, (uint32_t) seg->limit,
416                 (uint8_t) seg->type, seg->present, seg->dpl, seg->db, seg->s, seg->l, seg->g, seg->avl);
417 }
418
419 void kvm__show_registers(struct kvm *self)
420 {
421         unsigned long cr0, cr2, cr3;
422         unsigned long cr4, cr8;
423         unsigned long rax, rbx, rcx;
424         unsigned long rdx, rsi, rdi;
425         unsigned long rbp,  r8,  r9;
426         unsigned long r10, r11, r12;
427         unsigned long r13, r14, r15;
428         unsigned long rip, rsp;
429         struct kvm_sregs sregs;
430         unsigned long rflags;
431         struct kvm_regs regs;
432         int i;
433
434         if (ioctl(self->vcpu_fd, KVM_GET_REGS, &regs) < 0)
435                 die("KVM_GET_REGS failed");
436
437         rflags = regs.rflags;
438
439         rip = regs.rip; rsp = regs.rsp;
440         rax = regs.rax; rbx = regs.rbx; rcx = regs.rcx;
441         rdx = regs.rdx; rsi = regs.rsi; rdi = regs.rdi;
442         rbp = regs.rbp; r8  = regs.r8;  r9  = regs.r9;
443         r10 = regs.r10; r11 = regs.r11; r12 = regs.r12;
444         r13 = regs.r13; r14 = regs.r14; r15 = regs.r15;
445
446         printf("Registers:\n");
447         printf(" rip: %016lx   rsp: %016lx flags: %016lx\n", rip, rsp, rflags);
448         printf(" rax: %016lx   rbx: %016lx   rcx: %016lx\n", rax, rbx, rcx);
449         printf(" rdx: %016lx   rsi: %016lx   rdi: %016lx\n", rdx, rsi, rdi);
450         printf(" rbp: %016lx   r8:  %016lx   r9:  %016lx\n", rbp, r8,  r9);
451         printf(" r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
452         printf(" r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
453
454         if (ioctl(self->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
455                 die("KVM_GET_REGS failed");
456
457         cr0 = sregs.cr0; cr2 = sregs.cr2; cr3 = sregs.cr3;
458         cr4 = sregs.cr4; cr8 = sregs.cr8;
459
460         printf(" cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
461         printf(" cr4: %016lx   cr8: %016lx\n", cr4, cr8);
462         printf("Segment registers:\n");
463         printf(" register  selector  base              limit     type  p dpl db s l g avl\n");
464         print_segment("cs ", &sregs.cs);
465         print_segment("ss ", &sregs.ss);
466         print_segment("ds ", &sregs.ds);
467         print_segment("es ", &sregs.es);
468         print_segment("fs ", &sregs.fs);
469         print_segment("gs ", &sregs.gs);
470         print_segment("tr ", &sregs.tr);
471         print_segment("ldt", &sregs.ldt);
472         printf(" [ efer: %016lx  apic base: %016lx ]\n", (uint64_t) sregs.efer, (uint64_t) sregs.apic_base);
473         printf("Interrupt bitmap:\n");
474         printf(" ");
475         for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++)
476                 printf("%016lx ", (uint64_t) sregs.interrupt_bitmap[i]);
477         printf("\n");
478 }
479
480 void kvm__show_code(struct kvm *self)
481 {
482         unsigned int code_bytes = 64;
483         unsigned int code_prologue = code_bytes * 43 / 64;
484         unsigned int code_len = code_bytes;
485         unsigned char c;
486         unsigned int i;
487         uint8_t *ip;
488
489         if (ioctl(self->vcpu_fd, KVM_GET_REGS, &self->regs) < 0)
490                 die("KVM_GET_REGS failed");
491
492         if (ioctl(self->vcpu_fd, KVM_GET_SREGS, &self->sregs) < 0)
493                 die("KVM_GET_SREGS failed");
494
495         ip = guest_flat_to_host(self, ip_real_to_flat(self, self->regs.rip) - code_prologue);
496
497         printf("Code: ");
498
499         for (i = 0; i < code_len; i++, ip++) {
500                 c = *ip;
501
502                 if (ip == guest_flat_to_host(self, ip_real_to_flat(self, self->regs.rip)))
503                         printf("<%02x> ", c);
504                 else
505                         printf("%02x ", c);
506         }
507
508         printf("\n");
509 }