From mboxrd@z Thu Jan 1 00:00:00 1970 From: Anthony Liguori Subject: Re: kvm + kqemu enabled at the same time Date: Tue, 28 Oct 2008 17:06:48 -0500 Message-ID: <49078CF8.9070704@codemonkey.ws> References: <200810282220.59240.kejda@centrum.cz> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: kvm@vger.kernel.org To: =?ISO-8859-1?Q?Martin_Kej=EDk?= Return-path: Received: from rn-out-0910.google.com ([64.233.170.185]:4012 "EHLO rn-out-0910.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752773AbYJ1WGy (ORCPT ); Tue, 28 Oct 2008 18:06:54 -0400 Received: by rn-out-0910.google.com with SMTP id k40so1376701rnd.17 for ; Tue, 28 Oct 2008 15:06:53 -0700 (PDT) In-Reply-To: <200810282220.59240.kejda@centrum.cz> Sender: kvm-owner@vger.kernel.org List-ID: Martin Kej=EDk wrote: > Hello, > I've compiled the KVM enabled QEMU with support for both KVM and KQEM= U. Both modules loaded and > QEMU running saying "kvm: enabled" and "kqemu: enabled for user code"= =2E > > How does this work?? What does QEMU really do in this situation when = we look closer to CPU?? > =20 You're using both accelerators at the same time and getting 2x=20 acceleration. It will actually go faster than native now :-) Seriously, it's working based on sheer luck. If you look at the=20 cpu_exec() loop (which is the core execution loop in QEMU, you'll see): > #ifdef USE_KQEMU > if (kqemu_is_ok(env) && env->interrupt_request =3D=3D 0) = { > int ret; > env->eflags =3D env->eflags |=20 > cc_table[CC_OP].compute_all() | (DF & DF_MASK); > ret =3D kqemu_cpu_exec(env); > /* put eflags in CPU temporary format */ > CC_SRC =3D env->eflags & (CC_O | CC_S | CC_Z | CC_A |= =20 > CC_P | CC_C); > DF =3D 1 - (2 * ((env->eflags >> 10) & 1)); > CC_OP =3D CC_OP_EFLAGS; > env->eflags &=3D ~(DF_MASK | CC_O | CC_S | CC_Z | CC_= A |=20 > CC_P | CC_C); > if (ret =3D=3D 1) { > /* exception */ > longjmp(env->jmp_env, 1); > } else if (ret =3D=3D 2) { > /* softmmu execution needed */ > } else { > if (env->interrupt_request !=3D 0) { > /* hardware interrupt will be executed just=20 > after */ > } else { > /* otherwise, we restart */ > longjmp(env->jmp_env, 1); > } > } > } > #endif > > if (kvm_enabled()) { > kvm_cpu_exec(env); > longjmp(env->jmp_env, 1); > } What's letting this work is kqemu_is_ok(env). This check looks like th= is: > static inline int kqemu_is_ok(CPUState *env) > { > return(env->kqemu_enabled && > (env->cr[0] & CR0_PE_MASK) && > !(env->hflags & HF_INHIBIT_IRQ_MASK) && > (env->eflags & IF_MASK) && > !(env->eflags & VM_MASK) && > (env->kqemu_enabled =3D=3D 2 || > ((env->hflags & HF_CPL_MASK) =3D=3D 3 && > (env->eflags & IOPL_MASK) !=3D IOPL_MASK))); > } This is checking whether you're in protected mode, not in an interrupt=20 window, interrupts are enabled, you aren't in vm86 mode, and if not=20 using kernel-kqemu, CPL =3D=3D 3 and IOPL > CPL. As an optimization, KVM does not synchronize CPUState very often which=20 means that env is very stale. This means that it's likely that CPUStat= e=20 is in the initial CPU state (in real mode). As long as kqemu never gets to execute, you should be ok. If you force= =20 KVM to sync CPUState, you'll see kqemu actually execute and bad things=20 will happen. But the more important question is, why in the world are you doing this= =20 in the first place? Regards, Anthony Liguori > thanx > =20