From patchwork Sun Jun 22 21:23:18 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 4396801 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 8541A9F383 for ; Sun, 22 Jun 2014 21:25:21 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B6B202021A for ; Sun, 22 Jun 2014 21:25:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BDE15201DE for ; Sun, 22 Jun 2014 21:25:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752621AbaFVVZN (ORCPT ); Sun, 22 Jun 2014 17:25:13 -0400 Received: from cantor2.suse.de ([195.135.220.15]:33356 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752142AbaFVVXm (ORCPT ); Sun, 22 Jun 2014 17:23:42 -0400 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 27592AD66; Sun, 22 Jun 2014 21:23:38 +0000 (UTC) From: Alexander Graf To: kvm-ppc@vger.kernel.org Cc: kvm@vger.kernel.org Subject: [PATCH 14/33] KVM: PPC: Add std instruction emulation Date: Sun, 22 Jun 2014 23:23:18 +0200 Message-Id: <1403472217-22263-15-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.7.12.4 In-Reply-To: <1403472217-22263-1-git-send-email-agraf@suse.de> References: <1403472217-22263-1-git-send-email-agraf@suse.de> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch implements full emulation for the "std" instruction. It also implements all the the groundwork required to emulate store instructions in general as well as MMIO exits in emulated sections. Signed-off-by: Alexander Graf --- arch/powerpc/kvm/emulate.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++ arch/powerpc/kvm/powerpc.c | 6 +++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index 7bf247e0..0a5355d 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c @@ -305,10 +305,86 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(kvmppc_emulate_instruction); +static ulong get_addr(struct kvm_vcpu *vcpu, int offset, int ra) +{ + ulong addr = 0; +#if defined(CONFIG_PPC_BOOK3E_64) + ulong msr_64bit = MSR_CM; +#elif defined(CONFIG_PPC_BOOK3S_64) + ulong msr_64bit = MSR_SF; +#else + ulong msr_64bit = 0; +#endif + + if (ra) + addr = kvmppc_get_gpr(vcpu, ra); + + addr += offset; + if (!(kvmppc_get_msr(vcpu) & msr_64bit)) + addr = (uint32_t)addr; + + return addr; +} + +static int kvmppc_emulate_store(struct kvm_vcpu *vcpu, ulong addr, u64 value, + int size) +{ + ulong paddr = addr; + int r; + + if (kvmppc_need_byteswap(vcpu)) { + switch (size) { + case 1: *(u8*)&value = value; break; + case 2: *(u16*)&value = swab16(value); break; + case 4: *(u32*)&value = swab32(value); break; + case 8: *(u64*)&value = swab64(value); break; + } + } else { + switch (size) { + case 1: *(u8*)&value = value; break; + case 2: *(u16*)&value = value; break; + case 4: *(u32*)&value = value; break; + case 8: *(u64*)&value = value; break; + } + } + + r = kvmppc_st(vcpu, &paddr, size, &value, true); + switch (r) { + case -ENOENT: +#ifdef CONFIG_PPC_BOOK3S + kvmppc_core_queue_data_storage(vcpu, addr, + DSISR_ISSTORE | DSISR_NOHPTE); +#else + kvmppc_core_queue_dtlb_miss(vcpu, addr, ESR_DST | ESR_ST); +#endif + r = EMULATE_AGAIN; + break; + case -EPERM: +#ifdef CONFIG_PPC_BOOK3S + kvmppc_core_queue_data_storage(vcpu, addr, + DSISR_ISSTORE | DSISR_PROTFAULT); +#else + kvmppc_core_queue_data_storage(vcpu, addr, ESR_ST); +#endif + r = EMULATE_AGAIN; + break; + case EMULATE_DO_MMIO: + vcpu->stat.mmio_exits++; + vcpu->arch.paddr_accessed = paddr; + vcpu->arch.vaddr_accessed = addr; + vcpu->run->exit_reason = KVM_EXIT_MMIO; + r = kvmppc_emulate_loadstore(vcpu); + break; + } + + return r; +} + /* Emulates privileged and non-privileged instructions */ int kvmppc_emulate_any_instruction(struct kvm_vcpu *vcpu) { u32 inst = kvmppc_get_last_inst(vcpu); + ulong addr, value; enum emulation_result emulated = EMULATE_DONE; int advance = 1; @@ -316,8 +392,14 @@ int kvmppc_emulate_any_instruction(struct kvm_vcpu *vcpu) /* Try non-privileged instructions */ switch (get_op(inst)) { + case OP_STD: + addr = get_addr(vcpu, (s16)get_d(inst), get_ra(inst)); + value = kvmppc_get_gpr(vcpu, get_rs(inst)); + emulated = kvmppc_emulate_store(vcpu, addr, value, 8); + break; default: emulated = EMULATE_FAIL; + break; } /* Try privileged instructions */ diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index f2de6f4..0a326e1 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -158,8 +158,12 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu) if (kvmppc_needs_emulation(vcpu)) { /* Emulate one instruction, then try again */ local_irq_enable(); + vcpu->arch.last_inst = KVM_INST_FETCH_FAILED; - kvmppc_emulate_any_instruction(vcpu); + r = kvmppc_emulate_any_instruction(vcpu); + if (r == EMULATE_DO_MMIO) + return 0; + hard_irq_disable(); continue; }