]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Setup segmentation for the guest
authorPekka Enberg <penberg@cs.helsinki.fi>
Thu, 25 Mar 2010 18:37:48 +0000 (20:37 +0200)
committerPekka Enberg <penberg@cs.helsinki.fi>
Thu, 25 Mar 2010 18:54:45 +0000 (20:54 +0200)
This patch adds segmentation setup for the guest. It's not perfect yet as we
get KVM_EXIT_UNKNOWN but it's a start nevertheless.

Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
tools/kvm/include/kvm/kvm.h
tools/kvm/kvm.c

index 6f8d4b0cf8098fe6297a98fb1453a11eb3cc5a89..2f9ac2b23675a751c79460580c4d2db3e22782b2 100644 (file)
@@ -16,6 +16,7 @@ struct kvm {
        void                    *ram_start;
 
        struct kvm_regs         regs;
+       struct kvm_sregs        sregs;
 };
 
 struct kvm *kvm__init(void);
index 0848d3f1be785ffa780666a420501722f0fff074..9a2f0931cf62b48b7701f84bb655c90217958c4b 100644 (file)
@@ -191,11 +191,80 @@ uint32_t kvm__load_kernel(struct kvm *kvm, const char *kernel_filename)
 
 void kvm__reset_vcpu(struct kvm *self, uint64_t rip)
 {
-       self->regs.rip          = rip;
-       self->regs.rflags       = 0x0000000000000002ULL;
+       self->regs = (struct kvm_regs) {
+               .rip            = rip,
+               .rflags         = 0x0000000000000002ULL,
+       };
 
        if (ioctl(self->vcpu_fd, KVM_SET_REGS, &self->regs) < 0)
                die_perror("KVM_SET_REGS failed");
+
+       self->sregs = (struct kvm_sregs) {
+               .cr0            = 0x60000010ULL,
+               .cs             = (struct kvm_segment) {
+                       .selector       = 0xf000UL,
+                       .base           = 0xffff0000UL,
+                       .limit          = 0xffffU,
+                       .type           = 0x0bU,
+                       .present        = 1,
+                       .dpl            = 0x03,
+                       .s              = 1,
+               },
+               .ss             = (struct kvm_segment) {
+                       .limit          = 0xffffU,
+                       .type           = 0x03U,
+                       .present        = 1,
+                       .dpl            = 0x03,
+                       .s              = 1,
+               },
+               .ds             = (struct kvm_segment) {
+                       .limit          = 0xffffU,
+                       .type           = 0x03U,
+                       .present        = 1,
+                       .dpl            = 0x03,
+                       .s              = 1,
+               },
+               .es             = (struct kvm_segment) {
+                       .limit          = 0xffffU,
+                       .type           = 0x03U,
+                       .present        = 1,
+                       .dpl            = 0x03,
+                       .s              = 1,
+               },
+               .fs             = (struct kvm_segment) {
+                       .limit          = 0xffffU,
+                       .type           = 0x03U,
+                       .present        = 1,
+                       .dpl            = 0x03,
+                       .s              = 1,
+               },
+               .gs             = (struct kvm_segment) {
+                       .limit          = 0xffffU,
+                       .type           = 0x03U,
+                       .present        = 1,
+                       .dpl            = 0x03,
+                       .s              = 1,
+               },
+               .tr             = (struct kvm_segment) {
+                       .limit          = 0xffffU,
+                       .present        = 1,
+                       .type           = 0x03U,
+               },
+               .ldt            = (struct kvm_segment) {
+                       .limit          = 0xffffU,
+                       .present        = 1,
+                       .type           = 0x03U,
+               },
+               .gdt            = (struct kvm_dtable) {
+                       .limit          = 0xffffU,
+               },
+               .idt            = (struct kvm_dtable) {
+                       .limit          = 0xffffU,
+               },
+       };
+
+       if (ioctl(self->vcpu_fd, KVM_SET_SREGS, &self->sregs) < 0)
+               die_perror("KVM_SET_SREGS failed");
 }
 
 void kvm__run(struct kvm *self)
@@ -222,14 +291,24 @@ void kvm__emulate_io(struct kvm *self, uint16_t port, void *data, int direction,
                kvm__emulate_io_out(self, port, data, size, count);
 }
 
+static void print_segment(const char *name, struct kvm_segment *seg)
+{
+       printf(" %s        %04" PRIx16 "      %016" PRIx64 "  %08" PRIx32 "  %02" PRIx8 "    %x %x   %x  %x %x %x\n",
+               name, (uint16_t) seg->selector, (uint64_t) seg->base, (uint32_t) seg->limit,
+               (uint8_t) seg->type, seg->present, seg->dpl, seg->db, seg->s, seg->l, seg->g);
+}
+
 void kvm__show_registers(struct kvm *self)
 {
+       unsigned long cr0, cr2, cr3;
+       unsigned long cr4, cr8;
        unsigned long rax, rbx, rcx;
        unsigned long rdx, rsi, rdi;
        unsigned long rbp,  r8,  r9;
        unsigned long r10, r11, r12;
        unsigned long r13, r14, r15;
        unsigned long rip, rsp;
+       struct kvm_sregs sregs;
        unsigned long rflags;
        struct kvm_regs regs;
 
@@ -252,6 +331,23 @@ void kvm__show_registers(struct kvm *self)
        printf(" rbp: %016lx   r8:  %016lx   r9:  %016lx\n", rbp, r8,  r9);
        printf(" r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
        printf(" r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
+
+       if (ioctl(self->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
+               die("KVM_GET_REGS failed");
+
+       cr0 = sregs.cr0; cr2 = sregs.cr2; cr3 = sregs.cr3;
+       cr4 = sregs.cr4; cr8 = sregs.cr8;
+
+       printf("Segment registers:\n");
+       printf(" cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
+       printf(" cr4: %016lx   cr8: %016lx\n", cr4, cr8);
+       printf(" register  selector  base              limit     type  p dpl db s l g\n");
+       print_segment("cs", &sregs.cs);
+       print_segment("ss", &sregs.ss);
+       print_segment("ds", &sregs.ds);
+       print_segment("es", &sregs.es);
+       print_segment("fs", &sregs.fs);
+       print_segment("gs", &sregs.gs);
 }
 
 void kvm__show_code(struct kvm *self)