From patchwork Mon Apr 3 11:28:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 746410 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3vxVGx0HYGz9s83 for ; Mon, 3 Apr 2017 21:28:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751952AbdDCL2j (ORCPT ); Mon, 3 Apr 2017 07:28:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39754 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751759AbdDCL2j (ORCPT ); Mon, 3 Apr 2017 07:28:39 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 639B1C04B328; Mon, 3 Apr 2017 11:28:38 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 639B1C04B328 Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=thuth@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 639B1C04B328 Received: from thh440s.str.redhat.com (dhcp-192-189.str.redhat.com [10.33.192.189]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0A030A05DC; Mon, 3 Apr 2017 11:28:34 +0000 (UTC) From: Thomas Huth To: Paul Mackerras , kvm-ppc@vger.kernel.org Cc: kvm@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Laurent Vivier Subject: [PATCH] KVM: PPC: Book3S PR: Do not always inject facility unavailable exceptions Date: Mon, 3 Apr 2017 13:28:34 +0200 Message-Id: <1491218914-10992-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 03 Apr 2017 11:28:38 +0000 (UTC) Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org KVM should not inject a facility unavailable exception into the guest when it tries to execute a mtspr/mfspr instruction for an SPR that is unavailable, and the vCPU is *not* running in PRoblem state. It's right that we inject an exception when the vCPU is in PR mode, since chapter "6.2.10 Facility Status and Control Register" of the PowerISA v2.07 says that "When the FSCR makes a facility unavailable, attempted usage of the facility in *problem state* is treated as follows: [...] Access of an SPR using mfspr/mtspr causes a Facility Unavailable interrupt". But if the guest vCPU is not in PR mode, we should follow the behavior that is described in chapter "4.4.4 Move To/From System Register Instructions" instead and treat the instruction as a NOP. Signed-off-by: Thomas Huth --- arch/powerpc/kvm/book3s_pr.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index d4dfc0c..3e6c0b3 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -830,6 +831,31 @@ static void kvmppc_emulate_fac(struct kvm_vcpu *vcpu, ulong fac) } } +static void kvmppc_handle_fac_not_enabled(struct kvm_vcpu *vcpu, ulong fac) +{ + enum emulation_result er; + u32 inst; + + if (kvmppc_get_msr(vcpu) & MSR_PR) { + kvmppc_trigger_fac_interrupt(vcpu, fac); + return; + } + + er = kvmppc_get_last_inst(vcpu, INST_GENERIC, &inst); + if (er != EMULATE_DONE) + return; + + if (get_op(inst) == 31 && (get_xop(inst) == OP_31_XOP_MTSPR || + get_xop(inst) == OP_31_XOP_MFSPR)) { + /* mtspr and mfspr are treated as NOP for unsupported SPRs */ + kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4); + pr_debug_ratelimited("%s: write/read of disabled SPR: %d\n", + __func__, get_sprn(inst)); + } else { + kvmppc_trigger_fac_interrupt(vcpu, fac); + } +} + /* Enable facilities (TAR, EBB, DSCR) for the guest */ static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac) { @@ -855,7 +881,7 @@ static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac) if (!guest_fac_enabled) { /* Facility not enabled by the guest */ - kvmppc_trigger_fac_interrupt(vcpu, fac); + kvmppc_handle_fac_not_enabled(vcpu, fac); return RESUME_GUEST; }