From patchwork Thu Apr 1 19:35:27 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Wenhao Xu X-Patchwork-Id: 49238 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 8FA54B7C67 for ; Fri, 2 Apr 2010 06:36:39 +1100 (EST) Received: from localhost ([127.0.0.1]:34527 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NxQBv-0002hj-Jm for incoming@patchwork.ozlabs.org; Thu, 01 Apr 2010 15:36:35 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NxQBF-0002he-BH for qemu-devel@nongnu.org; Thu, 01 Apr 2010 15:35:53 -0400 Received: from [140.186.70.92] (port=42959 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NxQBC-0002hT-MH for qemu-devel@nongnu.org; Thu, 01 Apr 2010 15:35:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1NxQBB-0007tg-0p for qemu-devel@nongnu.org; Thu, 01 Apr 2010 15:35:50 -0400 Received: from mail-pw0-f45.google.com ([209.85.160.45]:51046) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1NxQBA-0007tT-L4 for qemu-devel@nongnu.org; Thu, 01 Apr 2010 15:35:48 -0400 Received: by pwi6 with SMTP id 6so1310443pwi.4 for ; Thu, 01 Apr 2010 12:35:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:in-reply-to:references :from:date:received:message-id:subject:to:cc:content-type :content-transfer-encoding; bh=7TELJPibGzIT0mEs/sG68yknZC0NFMbd7x09kvB54vs=; b=lhj3N3wRJDI1mPQuCKrTkY6+37pl8T3tvjVsHur7yCKS9cBsiv1oadJyDZnZeoKQp6 QejVZDDtj6rsYp/pw9TOEeruBlJaGMru0IYnY+/HjewdDC3HCdrvGrWcPrhv03FHJOUA Sv/7x/SlsIC15Yl1TUvtSCbdrUzovzUanTmkQ= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type:content-transfer-encoding; b=Mg4k8zsaaI6HAsnOh1qhNjrFZKIwHQZgrK2OyWShh+pOjY7q835FYsk2Iy3zBbJPb6 6Jq4m44OZ8AxJwowy11VU64KvH7Ckc8fQSg/uaHNCTVvYrpttiHXFwJWsGUA7tAkc5+P e/Nw1VZpCGezAwk9HllTB+fs9fr6qQghixDVg= MIME-Version: 1.0 Received: by 10.141.34.14 with HTTP; Thu, 1 Apr 2010 12:35:27 -0700 (PDT) In-Reply-To: <4BB45C63.3070401@redhat.com> References: <4BB45C63.3070401@redhat.com> From: Wenhao Xu Date: Thu, 1 Apr 2010 12:35:27 -0700 Received: by 10.141.13.5 with SMTP id q5mr969173rvi.280.1270150547069; Thu, 01 Apr 2010 12:35:47 -0700 (PDT) Message-ID: To: Avi Kivity X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: aliguori@us.ibm.com, paul@codesourcery.com, qemu-devel@nongnu.org, kvm@vger.kernel.org, Juan Quintela Subject: [Qemu-devel] Re: [questions] savevm|loadvm X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Does current qemu-kvm (qemu v0.12.3) use the irqchip, pit of KVM? I cannot find any KVM_CREATE_IRQCHIP and KVM_CREATE_PIT in the qemu code. Concerning the interface between qemu and kvm, I have the following confusion: 1. How irqchip and pit of KVM collaborating with the irq and pit emulation of QEMU? As far as I see, qemu-kvm still uses qemu's irq and pit emulation, doesn't it? 2. For return from KVM to QEMU, I cannot get the meaning of two exit reasons: case KVM_EXIT_EXCEPTION: What exception will cause KVM exit? default: dprintf("kvm_arch_handle_exit\n"); ret = kvm_arch_handle_exit(env, run); What exit reasons are default? 3. How could DMA interrupt the cpu when it finishes and the qemu-kvm is still running in kvm now? I am still working in the patch, but these confusions really prevent me moving forward. Thanks first for you guys giving me more hints. The following is the code so far I write: The main idea is synchronizing the CPU state and enter into the emulator mode when switching from kvm to emulator. I only do the switch when the exit reason is KVM_EXIT_IRQ_WINDOW_OPEN. However, I got the following errors: Whenever switch from kvm to qemu, the interrupt request in qemu will cause qemu enter into smm mode which is definitely a bug. This is the code that tries to synchronize the CPU state when the IRQ Window is open. And then tries to switch back to the QEMU emulator mode. +{ + CPUState *env = mon_get_cpu(); + env->ask_for_emulation = 0; + monitor_printf(mon, "Stop emulation\n"); +} + +static void do_is_emulation(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + CPUState *env = mon_get_cpu(); + if(env->is_in_emulation) + monitor_printf(mon, "Emulating now\n"); + else + monitor_printf(mon, "Virtualizing now\n"); +} + Thanks for the help, guys. I appreciate for your time to help! regards, Wenhao On Thu, Apr 1, 2010 at 1:42 AM, Avi Kivity wrote: > On 03/31/2010 02:31 PM, Juan Quintela wrote: >> >> Wenhao Xu  wrote: >> >>> >>> Hi, Juan, >>>    I am fresh to both QEMU and KVM. But so far, I notice that QEMU >>> uses "KVM_SET_USER_MEMORY_REGION" to set memory region that KVM can >>> use and uses cpu_register_physical_memory_offset to register the same >>> memory to QEMU emulator, which means QEMU and KVM use the same host >>> virtual memory. And therefore the memory KVM modified could be >>> directly reflected to QEMU. I don't quite understand the different >>> memory layout problem between the two. So I don't know exactly what >>> you mean to "fix" it? >>> >> >> 1st. qemu-kvm.git and qemu.git memory layouts are different, indeed with >> qemu.git kvm mode. (yes it is complex and weird). >> >> kvm vs qemu initialization is different.  Expecting to stop kvm, and run >> tcg from there is not going to work.  I guess it would need a lot of >> changes, but I haven't looked at it myself. >> > > I don't think it's so far fetched.  In fact early versions of qemu-kvm > switched between emulation and virtualization (emulate until 64-bit mode, > also emulate mmio instructions in qemu). > > Even today, all memory initialization is done via generic qemu mechanisms. >  So long as you synchronize all state (pit, irqchip, registers) you should > be fine. > >>>    For why switching is useful? Actually, I am a master student now >>> and doing a course project. What am I arguing is that QEMU could be >>> potentially useful to do many instrumentation analysis, but it is a >>> bit slow. So by combing with KVM, when the os runs to some place where >>> we are interested in, switch it to QEMU emulator mode and do the >>> analysis and then switch back. >>> >> >> idea is good, but I don't think that it is _so_ easy at this point.  tcg >> and kvm basically live in a different world.  Not sure of what needs to >> be done to make them back on sync. >> > > cpu_synchronize_state() > > -- > error compiling committee.c: too many arguments to function > > --- qemu-0.12.3/kvm-all.c 2010-02-23 12:54:38.000000000 -0800 +++ de-0.12.3/kvm-all.c 2010-04-01 12:23:07.000000000 -0700 @@ -577,7 +577,6 @@ { struct kvm_run *run = env->kvm_run; int ret; - dprintf("kvm_cpu_exec()\n"); do { @@ -641,7 +640,8 @@ dprintf("kvm_exit_unknown\n"); break; case KVM_EXIT_FAIL_ENTRY: - dprintf("kvm_exit_fail_entry\n"); + printf("kvm_exit_fail_entry\n"); + exit(1); break; case KVM_EXIT_EXCEPTION: dprintf("kvm_exit_exception\n"); @@ -670,7 +670,31 @@ env->exit_request = 0; env->exception_index = EXCP_INTERRUPT; } - + + /* de, start emulation */ + if(env->ask_for_emulation){ + //if( (env->eflags & IF_MASK) && (run->ready_for_interrupt_injection)){ + if(run->exit_reason == KVM_EXIT_IRQ_WINDOW_OPEN ){ + int saved_vm_running = vm_running; + vm_stop(0); + if (kvm_arch_get_registers(env)) { + printf("Fatal: kvm vcpu get registers failed\n"); + abort(); + } + env->kvm_state->regs_modified = 1; + env->is_in_emulation = 1; + target_ulong pc_start = env->segs[R_CS].base + env->eip; + /* int flags = env->hflags |(env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK)); */ + /* int code32 = !((flags >> HF_CS32_SHIFT) & 1); */ + printf("start emulation at pc: 0x%x, eip:0x%x\n", pc_start, env->eip); + /* target_disas(stderr, pc_start, 10, code32); */ + /* env->interrupt_request = 0; */ + printf("tr type:%d\n", (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf); + + if(saved_vm_running) + vm_start(); + } + } return ret; } ask_for_emulation is in the CPU_COMMON --- qemu-0.12.3/cpu-defs.h 2010-02-23 12:54:38.000000000 -0800 +++ de-0.12.3/cpu-defs.h 2010-03-28 15:17:14.000000000 -0700 @@ -197,6 +197,8 @@ const char *cpu_model_str; \ struct KVMState *kvm_state; \ struct kvm_run *kvm_run; \ - int kvm_fd; + int kvm_fd; \ + int ask_for_emulation; /* ask for emulation if 1 */ \ + int is_in_emulation; /* is in emulation */ when is_in_emulation, don't enter kvm again in cpu_exec --- qemu-0.12.3/cpu-exec.c 2010-02-23 12:54:38.000000000 -0800 +++ de-0.12.3/cpu-exec.c 2010-03-30 00:38:01.000000000 -0700 #if defined(TARGET_I386) - if (!kvm_enabled()) { - /* put eflags in CPU temporary format */ - CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); - DF = 1 - (2 * ((env->eflags >> 10) & 1)); - CC_OP = CC_OP_EFLAGS; - env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); - } + if (!kvm_enabled() || env->is_in_emulation) { + /* put eflags in CPU temporary format */ + CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); + DF = 1 - (2 * ((env->eflags >> 10) & 1)); + CC_OP = CC_OP_EFLAGS; + env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); + } - if (kvm_enabled()) { - kvm_cpu_exec(env); - longjmp(env->jmp_env, 1); - } + if (kvm_enabled() && !env->is_in_emulation) { + kvm_cpu_exec(env); + longjmp(env->jmp_env, 1); + } command "start_emulation", "stop_emulation" support in the monitor --- qemu-0.12.3/monitor.c 2010-02-23 12:54:38.000000000 -0800 +++ de-0.12.3/monitor.c 2010-03-28 15:16:18.000000000 -0700 @@ -56,6 +56,9 @@ #include "json-streamer.h" #include "json-parser.h" #include "osdep.h" +/* de */ +static void do_start_emulation(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + CPUState *env = mon_get_cpu(); + env->ask_for_emulation = 1; + monitor_printf(mon, "Starting emulation...\n"); +} + +static void do_stop_emulation(Monitor *mon, const QDict *qdict, QObject **ret_data)