]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm: Extract CPUID code into its own file
authorPekka Enberg <penberg@cs.helsinki.fi>
Wed, 31 Mar 2010 17:59:54 +0000 (20:59 +0300)
committerPekka Enberg <penberg@cs.helsinki.fi>
Wed, 31 Mar 2010 18:00:36 +0000 (21:00 +0300)
Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
tools/kvm/Makefile
tools/kvm/cpuid.c [new file with mode: 0644]
tools/kvm/include/kvm/kvm.h
tools/kvm/kvm.c
tools/kvm/main.c

index bb92bc450545e59716579605fadff5a6e7f80768..99b88c9295f50d12199dc9749c19b4fa30dbf024 100644 (file)
@@ -1,6 +1,7 @@
 PROGRAM        = kvm
 
 OBJS   += cpu.o
+OBJS   += cpuid.o
 OBJS   += interrupt.o
 OBJS   += kvm.o
 OBJS   += main.o
diff --git a/tools/kvm/cpuid.c b/tools/kvm/cpuid.c
new file mode 100644 (file)
index 0000000..0759ed7
--- /dev/null
@@ -0,0 +1,206 @@
+#include "kvm/kvm.h"
+
+#include "kvm/util.h"
+
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <assert.h>
+
+struct cpuid_regs {
+       uint32_t        eax;
+       uint32_t        ebx;
+       uint32_t        ecx;
+       uint32_t        edx;
+};
+
+static inline void
+cpuid(struct cpuid_regs *regs)
+{
+       asm("cpuid"
+           : "=a" (regs->eax),
+             "=b" (regs->ebx),
+             "=c" (regs->ecx),
+             "=d" (regs->edx)
+           : "0" (regs->eax), "2" (regs->ecx));
+}
+
+static struct kvm_cpuid2 *kvm_cpuid__new(unsigned long nent)
+{
+       struct kvm_cpuid2 *self;
+
+       self            = calloc(1, sizeof(*self) + (sizeof(struct kvm_cpuid_entry2) * nent));
+
+       if (!self)
+               die("out of memory");
+
+       return self;
+}
+
+static void kvm_cpuid__delete(struct kvm_cpuid2 *self)
+{
+       free(self);
+}
+
+#define        MAX_KVM_CPUID_ENTRIES           100
+
+enum {
+       CPUID_GET_VENDOR_ID             = 0x00,
+       CPUID_GET_HIGHEST_EXT_FUNCTION  = 0x80000000,
+};
+
+static uint32_t cpuid_highest_ext_func(void)
+{
+       struct cpuid_regs regs;
+
+       regs    = (struct cpuid_regs) {
+               .eax            = CPUID_GET_HIGHEST_EXT_FUNCTION,
+       };
+       cpuid(&regs);
+
+       return regs.eax;
+}
+
+static uint32_t cpuid_highest_func(void)
+{
+       struct cpuid_regs regs;
+
+       regs    = (struct cpuid_regs) {
+               .eax            = CPUID_GET_VENDOR_ID,
+       };
+       cpuid(&regs);
+
+       return regs.eax;
+}
+
+void kvm__setup_cpuid(struct kvm *self)
+{
+       struct kvm_cpuid2 *kvm_cpuid;
+       uint32_t highest_ext;
+       uint32_t function;
+       uint32_t highest;
+       uint32_t ndx = 0;
+
+       kvm_cpuid       = kvm_cpuid__new(MAX_KVM_CPUID_ENTRIES);
+
+       highest         = cpuid_highest_func();
+
+       for (function = 0; function < highest; function++) {
+               /*
+                * NOTE NOTE NOTE! Functions 0x0b and 0x0d seem to need special
+                * treatment as per qemu sources but we treat them as regular
+                * CPUID functions here because they are fairly exotic and the
+                * Linux kernel is not interested in them during boot up.
+                */
+               switch (function) {
+               case 0x02: {    /* Processor configuration descriptor */
+                       struct cpuid_regs regs;
+                       uint32_t times;
+
+                       regs    = (struct cpuid_regs) {
+                               .eax            = function,
+                       };
+                       cpuid(&regs);
+
+                       kvm_cpuid->entries[ndx++]       = (struct kvm_cpuid_entry2) {
+                               .function       = function,
+                               .index          = 0,
+                               .flags          = KVM_CPUID_FLAG_STATEFUL_FUNC | KVM_CPUID_FLAG_STATE_READ_NEXT,
+                               .eax            = regs.eax,
+                               .ebx            = regs.ebx,
+                               .ecx            = regs.ecx,
+                               .edx            = regs.edx,
+                       };
+
+                       times   = regs.eax & 0xff;      /* AL */
+
+                       while (times-- > 0) {
+                               regs    = (struct cpuid_regs) {
+                                       .eax            = function,
+                               };
+                               cpuid(&regs);
+
+                               kvm_cpuid->entries[ndx++]       = (struct kvm_cpuid_entry2) {
+                                       .function       = function,
+                                       .index          = 0,
+                                       .flags          = KVM_CPUID_FLAG_STATEFUL_FUNC,
+                                       .eax            = regs.eax,
+                                       .ebx            = regs.ebx,
+                                       .ecx            = regs.ecx,
+                                       .edx            = regs.edx,
+                               };
+                       }
+                       break;
+               }
+               case 0x04: {
+                       uint32_t index;
+
+                       for (index = 0; index < 2; index++) {
+                               struct cpuid_regs regs = {
+                                       .eax            = function,
+                                       .ecx            = index,
+                               };
+                               cpuid(&regs);
+
+                               kvm_cpuid->entries[ndx++]       = (struct kvm_cpuid_entry2) {
+                                       .function       = function,
+                                       .index          = index,
+                                       .flags          = KVM_CPUID_FLAG_SIGNIFCANT_INDEX,
+                                       .eax            = regs.eax,
+                                       .ebx            = regs.ebx,
+                                       .ecx            = regs.ecx,
+                                       .edx            = regs.edx,
+                               };
+                       }
+                       break;
+               }
+               default: {
+                       struct cpuid_regs regs;
+
+                       regs    = (struct cpuid_regs) {
+                               .eax            = function,
+                       };
+                       cpuid(&regs);
+
+                       kvm_cpuid->entries[ndx++]       = (struct kvm_cpuid_entry2) {
+                               .function       = function,
+                               .index          = 0,
+                               .flags          = 0,
+                               .eax            = regs.eax,
+                               .ebx            = regs.ebx,
+                               .ecx            = regs.ecx,
+                               .edx            = regs.edx,
+                       };
+                       break;
+               }};
+       }
+
+       highest_ext     = cpuid_highest_ext_func();
+
+       for (function = CPUID_GET_HIGHEST_EXT_FUNCTION; function < highest_ext; function++) {
+               struct cpuid_regs regs;
+
+               regs    = (struct cpuid_regs) {
+                       .eax            = function,
+               };
+               cpuid(&regs);
+
+               kvm_cpuid->entries[ndx++]       = (struct kvm_cpuid_entry2) {
+                       .function       = function,
+                       .index          = 0,
+                       .flags          = 0,
+                       .eax            = regs.eax,
+                       .ebx            = regs.ebx,
+                       .ecx            = regs.ecx,
+                       .edx            = regs.edx,
+               };
+       }
+
+       assert(ndx < MAX_KVM_CPUID_ENTRIES);
+
+       kvm_cpuid->nent         = ndx;
+
+       if (ioctl(self->vcpu_fd, KVM_SET_CPUID2, kvm_cpuid) < 0)
+               die_perror("KVM_SET_CPUID2 failed");
+
+       kvm_cpuid__delete(kvm_cpuid);
+}
index 1022177ab45b9fc1830a87a56c6a7840d6dd2976..d89a3f26fd5bfd8639ae311621a47070d6794eba 100644 (file)
@@ -28,6 +28,7 @@ struct kvm {
 };
 
 struct kvm *kvm__init(void);
+void kvm__setup_cpuid(struct kvm *self);
 void kvm__enable_singlestep(struct kvm *self);
 bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename, const char *kernel_cmdline);
 void kvm__reset_vcpu(struct kvm *self);
index 41f79431a12fd2b5dbbc890ecee418622ff593c8..0b7776557927f66d96899f424fad99a3ca2ead3c 100644 (file)
@@ -311,209 +311,8 @@ static inline uint32_t selector_to_base(uint16_t selector)
        return (uint32_t)selector * 16;
 }
 
-struct cpuid_regs {
-       uint32_t        eax;
-       uint32_t        ebx;
-       uint32_t        ecx;
-       uint32_t        edx;
-};
-
-static inline void
-cpuid(struct cpuid_regs *regs)
-{
-       asm("cpuid"
-           : "=a" (regs->eax),
-             "=b" (regs->ebx),
-             "=c" (regs->ecx),
-             "=d" (regs->edx)
-           : "0" (regs->eax), "2" (regs->ecx));
-}
-
-static struct kvm_cpuid2 *kvm_cpuid__new(unsigned long nent)
-{
-       struct kvm_cpuid2 *self;
-
-       self            = calloc(1, sizeof(*self) + (sizeof(struct kvm_cpuid_entry2) * nent));
-
-       if (!self)
-               die("out of memory");
-
-       return self;
-}
-
-static void kvm_cpuid__delete(struct kvm_cpuid2 *self)
-{
-       free(self);
-}
-
-#define        MAX_KVM_CPUID_ENTRIES           100
-
-enum {
-       CPUID_GET_VENDOR_ID             = 0x00,
-       CPUID_GET_HIGHEST_EXT_FUNCTION  = 0x80000000,
-};
-
-static uint32_t cpuid_highest_ext_func(void)
-{
-       struct cpuid_regs regs;
-
-       regs    = (struct cpuid_regs) {
-               .eax            = CPUID_GET_HIGHEST_EXT_FUNCTION,
-       };
-       cpuid(&regs);
-       
-       return regs.eax;
-}
-
-static uint32_t cpuid_highest_func(void)
-{
-       struct cpuid_regs regs;
-
-       regs    = (struct cpuid_regs) {
-               .eax            = CPUID_GET_VENDOR_ID,
-       };
-       cpuid(&regs);
-       
-       return regs.eax;
-}
-
-static void setup_cpuid(struct kvm *self)
-{
-       struct kvm_cpuid2 *kvm_cpuid;
-       uint32_t highest_ext;
-       uint32_t function;
-       uint32_t highest;
-       uint32_t ndx = 0;
-
-       kvm_cpuid       = kvm_cpuid__new(MAX_KVM_CPUID_ENTRIES);
-
-       highest         = cpuid_highest_func();
-
-       for (function = 0; function < highest; function++) {
-               /*
-                * NOTE NOTE NOTE! Functions 0x0b and 0x0d seem to need special
-                * treatment as per qemu sources but we treat them as regular
-                * CPUID functions here because they are fairly exotic and the
-                * Linux kernel is not interested in them during boot up.
-                */
-               switch (function) {
-               case 0x02: {    /* Processor configuration descriptor */
-                       struct cpuid_regs regs;
-                       uint32_t times;
-
-                       regs    = (struct cpuid_regs) {
-                               .eax            = function,
-                       };
-                       cpuid(&regs);
-
-                       kvm_cpuid->entries[ndx++]       = (struct kvm_cpuid_entry2) {
-                               .function       = function,
-                               .index          = 0,
-                               .flags          = KVM_CPUID_FLAG_STATEFUL_FUNC | KVM_CPUID_FLAG_STATE_READ_NEXT,
-                               .eax            = regs.eax,
-                               .ebx            = regs.ebx,
-                               .ecx            = regs.ecx,
-                               .edx            = regs.edx,
-                       };
-
-                       times   = regs.eax & 0xff;      /* AL */
-
-                       while (times-- > 0) {
-                               regs    = (struct cpuid_regs) {
-                                       .eax            = function,
-                               };
-                               cpuid(&regs);
-
-                               kvm_cpuid->entries[ndx++]       = (struct kvm_cpuid_entry2) {
-                                       .function       = function,
-                                       .index          = 0,
-                                       .flags          = KVM_CPUID_FLAG_STATEFUL_FUNC,
-                                       .eax            = regs.eax,
-                                       .ebx            = regs.ebx,
-                                       .ecx            = regs.ecx,
-                                       .edx            = regs.edx,
-                               };
-                       }
-                       break;
-               }
-               case 0x04: {
-                       uint32_t index;
-
-                       for (index = 0; index < 2; index++) {
-                               struct cpuid_regs regs = {
-                                       .eax            = function,
-                                       .ecx            = index,
-                               };
-                               cpuid(&regs);
-
-                               kvm_cpuid->entries[ndx++]       = (struct kvm_cpuid_entry2) {
-                                       .function       = function,
-                                       .index          = index,
-                                       .flags          = KVM_CPUID_FLAG_SIGNIFCANT_INDEX,
-                                       .eax            = regs.eax,
-                                       .ebx            = regs.ebx,
-                                       .ecx            = regs.ecx,
-                                       .edx            = regs.edx,
-                               };
-                       }
-                       break;
-               }
-               default: {
-                       struct cpuid_regs regs;
-
-                       regs    = (struct cpuid_regs) {
-                               .eax            = function,
-                       };
-                       cpuid(&regs);
-
-                       kvm_cpuid->entries[ndx++]       = (struct kvm_cpuid_entry2) {
-                               .function       = function,
-                               .index          = 0,
-                               .flags          = 0,
-                               .eax            = regs.eax,
-                               .ebx            = regs.ebx,
-                               .ecx            = regs.ecx,
-                               .edx            = regs.edx,
-                       };
-                       break;
-               }};
-       }
-
-       highest_ext     = cpuid_highest_ext_func();
-
-       for (function = CPUID_GET_HIGHEST_EXT_FUNCTION; function < highest_ext; function++) {
-               struct cpuid_regs regs;
-
-               regs    = (struct cpuid_regs) {
-                       .eax            = function,
-               };
-               cpuid(&regs);
-
-               kvm_cpuid->entries[ndx++]       = (struct kvm_cpuid_entry2) {
-                       .function       = function,
-                       .index          = 0,
-                       .flags          = 0,
-                       .eax            = regs.eax,
-                       .ebx            = regs.ebx,
-                       .ecx            = regs.ecx,
-                       .edx            = regs.edx,
-               };
-       }
-
-       assert(ndx < MAX_KVM_CPUID_ENTRIES);
-
-       kvm_cpuid->nent         = ndx;
-
-       if (ioctl(self->vcpu_fd, KVM_SET_CPUID2, kvm_cpuid) < 0)
-               die_perror("KVM_SET_CPUID2 failed");
-
-       kvm_cpuid__delete(kvm_cpuid);
-}
-
 void kvm__reset_vcpu(struct kvm *self)
 {
-       setup_cpuid(self);
-
        self->sregs = (struct kvm_sregs) {
                .cr0            = 0x60000010ULL,
                .cs             = (struct kvm_segment) {
index 184617c5cfa9eadf76e5596848294ffeb15fb82c..59303bfdb5f83ca28588d6e73006b3bb494265f3 100644 (file)
@@ -48,6 +48,8 @@ int main(int argc, char *argv[])
 
        kvm = kvm__init();
 
+       kvm__setup_cpuid(kvm);
+
        if (!kvm__load_kernel(kvm, kernel_filename, kernel_cmdline))
                die("unable to load kernel %s", kernel_filename);