From: Zhang Xiantao <[EMAIL PROTECTED]> Date: Mon, 3 Dec 2007 16:12:42 +0800 Subject: [PATCH] kvm: qemu: Split kvm_qemu_init_env. Using kvm_arch_qemu_init_env to hold x86-specific stuff. Moving corresponding static funtions to qemu-kvm-x86.c Changing back lm_capable_kernel to static variants. Signed-off-by: Zhang Xiantao <[EMAIL PROTECTED]> --- qemu/qemu-kvm-x86.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++- qemu/qemu-kvm.c | 137 +------------------------------------------------- qemu/qemu-kvm.h | 1 + 3 files changed, 142 insertions(+), 137 deletions(-)
diff --git a/qemu/qemu-kvm-x86.c b/qemu/qemu-kvm-x86.c
index ddb69df..a5df6d0 100644
--- a/qemu/qemu-kvm-x86.c
+++ b/qemu/qemu-kvm-x86.c
@@ -22,7 +22,7 @@ extern unsigned int kvm_shadow_memory;
extern kvm_context_t kvm_context;
static int kvm_has_msr_star;
-extern int lm_capable_kernel;
+static int lm_capable_kernel;
int kvm_arch_qemu_create_context(void)
{
@@ -414,4 +414,143 @@ void kvm_arch_save_regs(CPUState *env)
}
}
+static void host_cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx,
+ uint32_t *ecx, uint32_t *edx)
+{
+ uint32_t vec[4];
+
+ vec[0] = function;
+ asm volatile (
+#ifdef __x86_64__
+ "sub $128, %%rsp \n\t" /* skip red zone */
+ "push %0; push %%rsi \n\t"
+ "push %%rax; push %%rbx; push %%rcx; push %%rdx \n\t"
+ "mov 8*5(%%rsp), %%rsi \n\t"
+ "mov (%%rsi), %%eax \n\t"
+ "cpuid \n\t"
+ "mov %%eax, (%%rsi) \n\t"
+ "mov %%ebx, 4(%%rsi) \n\t"
+ "mov %%ecx, 8(%%rsi) \n\t"
+ "mov %%edx, 12(%%rsi) \n\t"
+ "pop %%rdx; pop %%rcx; pop %%rbx; pop %%rax \n\t"
+ "pop %%rsi; pop %0 \n\t"
+ "add $128, %%rsp"
+#else
+ "push %0; push %%esi \n\t"
+ "push %%eax; push %%ebx; push %%ecx; push %%edx \n\t"
+ "mov 4*5(%%esp), %%esi \n\t"
+ "mov (%%esi), %%eax \n\t"
+ "cpuid \n\t"
+ "mov %%eax, (%%esi) \n\t"
+ "mov %%ebx, 4(%%esi) \n\t"
+ "mov %%ecx, 8(%%esi) \n\t"
+ "mov %%edx, 12(%%esi) \n\t"
+ "pop %%edx; pop %%ecx; pop %%ebx; pop %%eax \n\t"
+ "pop %%esi; pop %0 \n\t"
+#endif
+ : : "rm"(vec) : "memory");
+ if (eax)
+ *eax = vec[0];
+ if (ebx)
+ *ebx = vec[1];
+ if (ecx)
+ *ecx = vec[2];
+ if (edx)
+ *edx = vec[3];
+}
+
+
+static void do_cpuid_ent(struct kvm_cpuid_entry *e, uint32_t function,
+ CPUState *env)
+{
+ env->regs[R_EAX] = function;
+ qemu_kvm_cpuid_on_env(env);
+ e->function = function;
+ e->eax = env->regs[R_EAX];
+ e->ebx = env->regs[R_EBX];
+ e->ecx = env->regs[R_ECX];
+ e->edx = env->regs[R_EDX];
+ if (function == 0x80000001) {
+ uint32_t h_eax, h_edx;
+ struct utsname utsname;
+
+ host_cpuid(function, &h_eax, NULL, NULL, &h_edx);
+ uname(&utsname);
+ lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0;
+
+ // long mode
+ if ((h_edx & 0x20000000) == 0 || !lm_capable_kernel)
+ e->edx &= ~0x20000000u;
+ // syscall
+ if ((h_edx & 0x00000800) == 0)
+ e->edx &= ~0x00000800u;
+ // nx
+ if ((h_edx & 0x00100000) == 0)
+ e->edx &= ~0x00100000u;
+ // svm
+ if (e->ecx & 4)
+ e->ecx &= ~4u;
+ }
+ // sysenter isn't supported on compatibility mode on AMD. and
syscall
+ // isn't supported in compatibility mode on Intel. so advertise
the
+ // actuall cpu, and say goodbye to migration between different
vendors
+ // is you use compatibility mode.
+ if (function == 0) {
+ uint32_t bcd[3];
+
+ host_cpuid(0, NULL, &bcd[0], &bcd[1], &bcd[2]);
+ e->ebx = bcd[0];
+ e->ecx = bcd[1];
+ e->edx = bcd[2];
+ }
+}
+
+int kvm_arch_qemu_init_env(CPUState *cenv)
+{
+ struct kvm_cpuid_entry cpuid_ent[100];
+#ifdef KVM_CPUID_SIGNATURE
+ struct kvm_cpuid_entry *pv_ent;
+ uint32_t signature[3];
+#endif
+ int cpuid_nent = 0;
+ CPUState copy;
+ uint32_t i, limit;
+
+ copy = *cenv;
+
+#ifdef KVM_CPUID_SIGNATURE
+ /* Paravirtualization CPUIDs */
+ memcpy(signature, "KVMKVMKVM", 12);
+ pv_ent = &cpuid_ent[cpuid_nent++];
+ memset(pv_ent, 0, sizeof(*pv_ent));
+ pv_ent->function = KVM_CPUID_SIGNATURE;
+ pv_ent->eax = 0;
+ pv_ent->ebx = signature[0];
+ pv_ent->ecx = signature[1];
+ pv_ent->edx = signature[2];
+
+ pv_ent = &cpuid_ent[cpuid_nent++];
+ memset(pv_ent, 0, sizeof(*pv_ent));
+ pv_ent->function = KVM_CPUID_FEATURES;
+ pv_ent->eax = 0;
+#endif
+
+ copy.regs[R_EAX] = 0;
+ qemu_kvm_cpuid_on_env(©);
+ limit = copy.regs[R_EAX];
+
+ for (i = 0; i <= limit; ++i)
+ do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, ©);
+
+ copy.regs[R_EAX] = 0x80000000;
+ qemu_kvm_cpuid_on_env(©);
+ limit = copy.regs[R_EAX];
+
+ for (i = 0x80000000; i <= limit; ++i)
+ do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, ©);
+
+ kvm_setup_cpuid(kvm_context, cenv->cpu_index, cpuid_nent,
cpuid_ent);
+ return 0;
+}
+
#endif
diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c
index df90ffb..2812a89 100644
--- a/qemu/qemu-kvm.c
+++ b/qemu/qemu-kvm.c
@@ -9,7 +9,6 @@
#endif
int kvm_allowed = KVM_ALLOWED_DEFAULT;
-int lm_capable_kernel;
int kvm_irqchip = 1;
#ifdef USE_KVM
@@ -691,143 +690,9 @@ int kvm_qemu_check_extension(int ext)
return kvm_check_extension(kvm_context, ext);
}
-static void host_cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx,
- uint32_t *ecx, uint32_t *edx)
-{
- uint32_t vec[4];
-
- vec[0] = function;
- asm volatile (
-#ifdef __x86_64__
- "sub $128, %%rsp \n\t" /* skip red zone */
- "push %0; push %%rsi \n\t"
- "push %%rax; push %%rbx; push %%rcx; push %%rdx \n\t"
- "mov 8*5(%%rsp), %%rsi \n\t"
- "mov (%%rsi), %%eax \n\t"
- "cpuid \n\t"
- "mov %%eax, (%%rsi) \n\t"
- "mov %%ebx, 4(%%rsi) \n\t"
- "mov %%ecx, 8(%%rsi) \n\t"
- "mov %%edx, 12(%%rsi) \n\t"
- "pop %%rdx; pop %%rcx; pop %%rbx; pop %%rax \n\t"
- "pop %%rsi; pop %0 \n\t"
- "add $128, %%rsp"
-#else
- "push %0; push %%esi \n\t"
- "push %%eax; push %%ebx; push %%ecx; push %%edx \n\t"
- "mov 4*5(%%esp), %%esi \n\t"
- "mov (%%esi), %%eax \n\t"
- "cpuid \n\t"
- "mov %%eax, (%%esi) \n\t"
- "mov %%ebx, 4(%%esi) \n\t"
- "mov %%ecx, 8(%%esi) \n\t"
- "mov %%edx, 12(%%esi) \n\t"
- "pop %%edx; pop %%ecx; pop %%ebx; pop %%eax \n\t"
- "pop %%esi; pop %0 \n\t"
-#endif
- : : "rm"(vec) : "memory");
- if (eax)
- *eax = vec[0];
- if (ebx)
- *ebx = vec[1];
- if (ecx)
- *ecx = vec[2];
- if (edx)
- *edx = vec[3];
-}
-
-static void do_cpuid_ent(struct kvm_cpuid_entry *e, uint32_t function,
- CPUState *env)
-{
- env->regs[R_EAX] = function;
- qemu_kvm_cpuid_on_env(env);
- e->function = function;
- e->eax = env->regs[R_EAX];
- e->ebx = env->regs[R_EBX];
- e->ecx = env->regs[R_ECX];
- e->edx = env->regs[R_EDX];
- if (function == 0x80000001) {
- uint32_t h_eax, h_edx;
- struct utsname utsname;
-
- host_cpuid(function, &h_eax, NULL, NULL, &h_edx);
- uname(&utsname);
- lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0;
-
- // long mode
- if ((h_edx & 0x20000000) == 0 || !lm_capable_kernel)
- e->edx &= ~0x20000000u;
- // syscall
- if ((h_edx & 0x00000800) == 0)
- e->edx &= ~0x00000800u;
- // nx
- if ((h_edx & 0x00100000) == 0)
- e->edx &= ~0x00100000u;
- // svm
- if (e->ecx & 4)
- e->ecx &= ~4u;
- }
- // sysenter isn't supported on compatibility mode on AMD. and
syscall
- // isn't supported in compatibility mode on Intel. so advertise
the
- // actuall cpu, and say goodbye to migration between different
vendors
- // is you use compatibility mode.
- if (function == 0) {
- uint32_t bcd[3];
-
- host_cpuid(0, NULL, &bcd[0], &bcd[1], &bcd[2]);
- e->ebx = bcd[0];
- e->ecx = bcd[1];
- e->edx = bcd[2];
- }
-}
-
int kvm_qemu_init_env(CPUState *cenv)
{
- struct kvm_cpuid_entry cpuid_ent[100];
-#ifdef KVM_CPUID_SIGNATURE
- struct kvm_cpuid_entry *pv_ent;
- uint32_t signature[3];
-#endif
- int cpuid_nent = 0;
- CPUState copy;
- uint32_t i, limit;
-
- copy = *cenv;
-
-#ifdef KVM_CPUID_SIGNATURE
- /* Paravirtualization CPUIDs */
- memcpy(signature, "KVMKVMKVM", 12);
- pv_ent = &cpuid_ent[cpuid_nent++];
- memset(pv_ent, 0, sizeof(*pv_ent));
- pv_ent->function = KVM_CPUID_SIGNATURE;
- pv_ent->eax = 0;
- pv_ent->ebx = signature[0];
- pv_ent->ecx = signature[1];
- pv_ent->edx = signature[2];
-
- pv_ent = &cpuid_ent[cpuid_nent++];
- memset(pv_ent, 0, sizeof(*pv_ent));
- pv_ent->function = KVM_CPUID_FEATURES;
- pv_ent->eax = 0;
-#endif
-
- copy.regs[R_EAX] = 0;
- qemu_kvm_cpuid_on_env(©);
- limit = copy.regs[R_EAX];
-
- for (i = 0; i <= limit; ++i)
- do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, ©);
-
- copy.regs[R_EAX] = 0x80000000;
- qemu_kvm_cpuid_on_env(©);
- limit = copy.regs[R_EAX];
-
- for (i = 0x80000000; i <= limit; ++i)
- do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, ©);
-
- kvm_setup_cpuid(kvm_context, cenv->cpu_index, cpuid_nent,
cpuid_ent);
-
- return 0;
+ return kvm_arch_qemu_init_env(cenv);
}
int kvm_update_debugger(CPUState *env)
diff --git a/qemu/qemu-kvm.h b/qemu/qemu-kvm.h
index 1f7321e..212e1ca 100644
--- a/qemu/qemu-kvm.h
+++ b/qemu/qemu-kvm.h
@@ -32,6 +32,7 @@ int kvm_arch_qemu_create_context(void);
void kvm_arch_save_regs(CPUState *env);
void kvm_arch_load_regs(CPUState *env);
+int kvm_arch_qemu_init_env(CPUState *cenv);
#define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1))
#define BITMAP_SIZE(m) (ALIGN(((m)>>TARGET_PAGE_BITS), HOST_LONG_BITS)
/ 8)
--
1.5.1.2
0004-kvm-qemu-Split-kvm_qemu_init_env.patch
Description: 0004-kvm-qemu-Split-kvm_qemu_init_env.patch
------------------------------------------------------------------------- SF.Net email is sponsored by: The Future of Linux Business White Paper from Novell. From the desktop to the data center, Linux is going mainstream. Let it simplify your IT future. http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________ kvm-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/kvm-devel
