From patchwork Tue Jun 1 21:46:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabiano Rosas X-Patchwork-Id: 12292257 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55B5FC47080 for ; Tue, 1 Jun 2021 21:49:13 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C3802611CA for ; Tue, 1 Jun 2021 21:49:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C3802611CA Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.ibm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:48434 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1loCG7-0005Bf-T8 for qemu-devel@archiver.kernel.org; Tue, 01 Jun 2021 17:49:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33812) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1loCE7-0001js-Ol; Tue, 01 Jun 2021 17:47:07 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:49050 helo=mx0a-001b2d01.pphosted.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1loCE5-0004L3-Pq; Tue, 01 Jun 2021 17:47:07 -0400 Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 151LZ4du008232; Tue, 1 Jun 2021 17:46:57 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=FnsaOC4D7Yh9fRvenSTiJG+0WYku/Lut/jlSYrzuTlU=; b=IAZTUHJNOBv4QJZ1Y5XX3JkMMWpo71FvrEJuWK+nzS1N/3Ii8h7hIhE4dCjC4b5d922N 1a0dl2LxRSqM3mnMSWNiZfXFyxUa41SAl3HAUhcieiG3yaN8eW/WLR2OdkUVPX1kM0xV +tS6yOBgQgtXd5uaSEy/r/9TzzDyEGgVvmSjGmSaFEDDp9O+yf82HM37onDIutLXz7Si IzjqkKJcc4OsVtcM8l+0Wv9L97H+wPrSAiL8VdAlK6btJBv8KlW+q1QLH8EB8tuoe8Z7 Fsl5nx2Vx7J75s7Lpf0NtE8bLGJt29HVv12dXv4PEvU6GNlGaO5Rh3rgUrxmxScl14to uQ== Received: from ppma02wdc.us.ibm.com (aa.5b.37a9.ip4.static.sl-reverse.com [169.55.91.170]) by mx0b-001b2d01.pphosted.com with ESMTP id 38wu1a39kb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 01 Jun 2021 17:46:57 -0400 Received: from pps.filterd (ppma02wdc.us.ibm.com [127.0.0.1]) by ppma02wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 151LgiWr019169; Tue, 1 Jun 2021 21:46:57 GMT Received: from b03cxnp08026.gho.boulder.ibm.com (b03cxnp08026.gho.boulder.ibm.com [9.17.130.18]) by ppma02wdc.us.ibm.com with ESMTP id 38ud89jqm0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 01 Jun 2021 21:46:57 +0000 Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp08026.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 151LkuQo16712142 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 1 Jun 2021 21:46:56 GMT Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id F0D9078063; Tue, 1 Jun 2021 21:46:55 +0000 (GMT) Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 96B6278060; Tue, 1 Jun 2021 21:46:54 +0000 (GMT) Received: from farosas.linux.ibm.com.com (unknown [9.211.142.192]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP; Tue, 1 Jun 2021 21:46:54 +0000 (GMT) From: Fabiano Rosas To: qemu-devel@nongnu.org Subject: [RFC PATCH 1/5] target/ppc: powerpc_excp: Move lpes code to where it is used Date: Tue, 1 Jun 2021 18:46:45 -0300 Message-Id: <20210601214649.785647-2-farosas@linux.ibm.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210601214649.785647-1-farosas@linux.ibm.com> References: <20210601214649.785647-1-farosas@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: D3jdj7F9pvVVCm1JuJO9Bgd8eZb_7YSo X-Proofpoint-ORIG-GUID: D3jdj7F9pvVVCm1JuJO9Bgd8eZb_7YSo X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.761 definitions=2021-06-01_12:2021-06-01, 2021-06-01 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 impostorscore=0 mlxscore=0 lowpriorityscore=0 clxscore=1015 suspectscore=0 adultscore=0 malwarescore=0 phishscore=0 spamscore=0 mlxlogscore=999 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104190000 definitions=main-2106010143 Received-SPF: pass client-ip=148.163.158.5; envelope-from=farosas@linux.ibm.com; helo=mx0a-001b2d01.pphosted.com X-Spam_score_int: -19 X-Spam_score: -2.0 X-Spam_bar: -- X-Spam_report: (-2.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-ppc@nongnu.org, groug@kaod.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Fabiano Rosas --- target/ppc/excp_helper.c | 47 +++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 04418054f5..5ea8503b46 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -333,7 +333,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) CPUPPCState *env = &cpu->env; target_ulong msr, new_msr, vector; int srr0, srr1, asrr0, asrr1, lev = -1; - bool lpes0; qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx " => %08x (%02x)\n", env->nip, excp, env->error_code); @@ -365,27 +364,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) excp = powerpc_reset_wakeup(cs, env, excp, &msr); } - /* - * Exception targeting modifiers - * - * LPES0 is supported on POWER7/8/9 - * LPES1 is not supported (old iSeries mode) - * - * On anything else, we behave as if LPES0 is 1 - * (externals don't alter MSR:HV) - */ -#if defined(TARGET_PPC64) - if (excp_model == POWERPC_EXCP_POWER7 || - excp_model == POWERPC_EXCP_POWER8 || - excp_model == POWERPC_EXCP_POWER9 || - excp_model == POWERPC_EXCP_POWER10) { - lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); - } else -#endif /* defined(TARGET_PPC64) */ - { - lpes0 = true; - } - /* * Hypervisor emulation assistance interrupt only exists on server * arch 2.05 server or later. We also don't want to generate it if @@ -473,8 +451,32 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) msr |= env->error_code; break; case POWERPC_EXCP_EXTERNAL: /* External input */ + { + bool lpes0; + cs = CPU(cpu); + /* + * Exception targeting modifiers + * + * LPES0 is supported on POWER7/8/9 + * LPES1 is not supported (old iSeries mode) + * + * On anything else, we behave as if LPES0 is 1 + * (externals don't alter MSR:HV) + */ +#if defined(TARGET_PPC64) + if (excp_model == POWERPC_EXCP_POWER7 || + excp_model == POWERPC_EXCP_POWER8 || + excp_model == POWERPC_EXCP_POWER9 || + excp_model == POWERPC_EXCP_POWER10) { + lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); + } else +#endif /* defined(TARGET_PPC64) */ + { + lpes0 = true; + } + if (!lpes0) { new_msr |= (target_ulong)MSR_HVB; new_msr |= env->msr & ((target_ulong)1 << MSR_RI); @@ -486,6 +488,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); } break; + } case POWERPC_EXCP_ALIGN: /* Alignment exception */ /* Get rS/rD and rA from faulting opcode */ /* From patchwork Tue Jun 1 21:46:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabiano Rosas X-Patchwork-Id: 12292263 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EE744C47092 for ; Tue, 1 Jun 2021 21:50:53 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9C994611CA for ; Tue, 1 Jun 2021 21:50:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9C994611CA Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.ibm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:54248 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1loCHk-0000h7-LX for qemu-devel@archiver.kernel.org; Tue, 01 Jun 2021 17:50:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33902) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1loCEC-0001zQ-Jp; Tue, 01 Jun 2021 17:47:12 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:57878) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1loCEA-0004QR-Ee; Tue, 01 Jun 2021 17:47:12 -0400 Received: from pps.filterd (m0127361.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 151LXIa9038846; Tue, 1 Jun 2021 17:46:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=sD8S3a2Gsav+xN9eAy6cVsGC6pSkLRF9/1GtP90p3bE=; b=by1qgrt4aFtxQ9FicApelwuZLvpJvM1K9RGPU0OCTmoypbFr0oQr/KU9mFS72xVqteZa Tq3U/FikJM3EGlWYGOodRL5FygzwcIYH94BfWo7i7AFAGE7a+jYC0aaWxKTvjLA/wGvF 8v8oEGV9NijqlJpQ2pl9r/MNTDR22J3r066SZGJXHswBaaXA1MOnyVYDq1yd97hv5dt4 5XvvYjBbgGB4imj9khbqDHFzyaDmehb9HLzHaILLWJaeX2CxcHHERLJUDZ0HF4i4AyEb O5ZoG5Ze+zlak6ZB+sfqon/dUGonNTnQuUEw0VFZF//lCHa/Bu50iQM6uR70h4s2p3iI ng== Received: from ppma02wdc.us.ibm.com (aa.5b.37a9.ip4.static.sl-reverse.com [169.55.91.170]) by mx0a-001b2d01.pphosted.com with ESMTP id 38wuagjrwd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 01 Jun 2021 17:46:59 -0400 Received: from pps.filterd (ppma02wdc.us.ibm.com [127.0.0.1]) by ppma02wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 151LghLe019162; Tue, 1 Jun 2021 21:46:58 GMT Received: from b03cxnp08027.gho.boulder.ibm.com (b03cxnp08027.gho.boulder.ibm.com [9.17.130.19]) by ppma02wdc.us.ibm.com with ESMTP id 38ud89jqm4-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 01 Jun 2021 21:46:58 +0000 Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp08027.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 151LkvcL13042174 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 1 Jun 2021 21:46:57 GMT Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AACA078064; Tue, 1 Jun 2021 21:46:57 +0000 (GMT) Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5B74478063; Tue, 1 Jun 2021 21:46:56 +0000 (GMT) Received: from farosas.linux.ibm.com.com (unknown [9.211.142.192]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP; Tue, 1 Jun 2021 21:46:56 +0000 (GMT) From: Fabiano Rosas To: qemu-devel@nongnu.org Subject: [RFC PATCH 2/5] target/ppc: powerpc_excp: Remove dump_syscall_vectored Date: Tue, 1 Jun 2021 18:46:46 -0300 Message-Id: <20210601214649.785647-3-farosas@linux.ibm.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210601214649.785647-1-farosas@linux.ibm.com> References: <20210601214649.785647-1-farosas@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: WdnsQLFFNB6TtUpPC--EZVCHiJGKMDqh X-Proofpoint-GUID: WdnsQLFFNB6TtUpPC--EZVCHiJGKMDqh X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.761 definitions=2021-06-01_12:2021-06-01, 2021-06-01 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 mlxscore=0 malwarescore=0 adultscore=0 priorityscore=1501 mlxlogscore=924 spamscore=0 suspectscore=0 phishscore=0 impostorscore=0 bulkscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104190000 definitions=main-2106010143 Received-SPF: pass client-ip=148.163.158.5; envelope-from=farosas@linux.ibm.com; helo=mx0b-001b2d01.pphosted.com X-Spam_score_int: -19 X-Spam_score: -2.0 X-Spam_bar: -- X-Spam_report: (-2.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-ppc@nongnu.org, groug@kaod.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This function is identical to dump_syscall, so use the latter for system call vectored as well. Signed-off-by: Fabiano Rosas --- target/ppc/excp_helper.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 5ea8503b46..9e3aae1c96 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -70,18 +70,6 @@ static inline void dump_syscall(CPUPPCState *env) ppc_dump_gpr(env, 8), env->nip); } -static inline void dump_syscall_vectored(CPUPPCState *env) -{ - qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 - " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 - " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64 - " nip=" TARGET_FMT_lx "\n", - ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), - ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5), - ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7), - ppc_dump_gpr(env, 8), env->nip); -} - static inline void dump_hcall(CPUPPCState *env) { qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64 @@ -564,7 +552,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) break; case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ lev = env->error_code; - dump_syscall_vectored(env); + dump_syscall(env); env->nip += 4; new_msr |= env->msr & ((target_ulong)1 << MSR_EE); new_msr |= env->msr & ((target_ulong)1 << MSR_RI); From patchwork Tue Jun 1 21:46:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabiano Rosas X-Patchwork-Id: 12292255 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8EF16C47080 for ; Tue, 1 Jun 2021 21:48:31 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D7885613B9 for ; Tue, 1 Jun 2021 21:48:30 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D7885613B9 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.ibm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:47294 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1loCFR-0004Pn-QV for qemu-devel@archiver.kernel.org; Tue, 01 Jun 2021 17:48:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33844) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1loCE9-0001pS-NV; Tue, 01 Jun 2021 17:47:09 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:25604) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1loCE7-0004NV-LY; Tue, 01 Jun 2021 17:47:09 -0400 Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 151LYN8J030530; Tue, 1 Jun 2021 17:47:01 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=Gr5y5WAcVJ3ba6eDGooURqSwmsFn14XiQYvczcDFKd0=; b=JI/1aJqQn9ZI1UviCl/5nWPxm6QMn6HjVp0NmtZybmNM1XUFE+EV0CHjSSuiZX5HIUJD A5Pmj/S1CzGpKfy801qULlox5ldA1rYNay9eIotFbz+QSAq4V0TKuVPv429mPB5a4Zkf f2rhrZwKc178Jdh/zyFTL77qpQvvLYrxrFcv41+SzW2Ly73T9Q8HdISXXo5mqTnn/BHY 3E3rsDZPqGvallysOQoqRAiQa3xWUt0s9F0C1wyQApP5zftss7PsWkNFioU0t8Xhd2r8 OJkppMNBJFTZWER7Lz4V/hppqaAqmHufysO/hozsr5gr7zpUqRVM3Dn5SObYhzH1yyrt vw== Received: from ppma01dal.us.ibm.com (83.d6.3fa9.ip4.static.sl-reverse.com [169.63.214.131]) by mx0a-001b2d01.pphosted.com with ESMTP id 38wv6whabb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 01 Jun 2021 17:47:01 -0400 Received: from pps.filterd (ppma01dal.us.ibm.com [127.0.0.1]) by ppma01dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 151LgYCJ017203; Tue, 1 Jun 2021 21:47:00 GMT Received: from b03cxnp07028.gho.boulder.ibm.com (b03cxnp07028.gho.boulder.ibm.com [9.17.130.15]) by ppma01dal.us.ibm.com with ESMTP id 38ud89hdch-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 01 Jun 2021 21:47:00 +0000 Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp07028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 151LkxGh20644348 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 1 Jun 2021 21:46:59 GMT Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 82B8E7805C; Tue, 1 Jun 2021 21:46:59 +0000 (GMT) Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 30CD778060; Tue, 1 Jun 2021 21:46:58 +0000 (GMT) Received: from farosas.linux.ibm.com.com (unknown [9.211.142.192]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP; Tue, 1 Jun 2021 21:46:57 +0000 (GMT) From: Fabiano Rosas To: qemu-devel@nongnu.org Subject: [RFC PATCH 3/5] target/ppc: powerpc_excp: Consolidade TLB miss code Date: Tue, 1 Jun 2021 18:46:47 -0300 Message-Id: <20210601214649.785647-4-farosas@linux.ibm.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210601214649.785647-1-farosas@linux.ibm.com> References: <20210601214649.785647-1-farosas@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: tD3wsGtvV__48-87US8orgynNuvFqebC X-Proofpoint-ORIG-GUID: tD3wsGtvV__48-87US8orgynNuvFqebC X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.761 definitions=2021-06-01_10:2021-06-01, 2021-06-01 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 priorityscore=1501 suspectscore=0 adultscore=0 phishscore=0 mlxlogscore=878 bulkscore=0 impostorscore=0 malwarescore=0 clxscore=1015 mlxscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104190000 definitions=main-2106010143 Received-SPF: pass client-ip=148.163.156.1; envelope-from=farosas@linux.ibm.com; helo=mx0a-001b2d01.pphosted.com X-Spam_score_int: -19 X-Spam_score: -2.0 X-Spam_bar: -- X-Spam_report: (-2.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-ppc@nongnu.org, groug@kaod.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" The only difference in the code for Instruction fetch, Data load and Data store TLB miss errors is that when called from an unsupported processor (i.e. not one of 602, 603, 603e, G2, 7x5 or 74xx), they abort with a message specific to the operation type (insn fetch, data load/store). If a processor does not support those interrupts we should not be registering them in init_excp_ to begin with, so that error message would never be used. I'm leaving the message in for completeness, but making it generic and consolidating the three interrupts into the same case statement body. Signed-off-by: Fabiano Rosas --- target/ppc/excp_helper.c | 37 ++----------------------------------- 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 9e3aae1c96..fd147e2a37 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -689,52 +689,20 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) "is not implemented yet !\n"); break; case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ - switch (excp_model) { - case POWERPC_EXCP_602: - case POWERPC_EXCP_603: - case POWERPC_EXCP_603E: - case POWERPC_EXCP_G2: - goto tlb_miss_tgpr; - case POWERPC_EXCP_7x5: - goto tlb_miss; - case POWERPC_EXCP_74xx: - goto tlb_miss_74xx; - default: - cpu_abort(cs, "Invalid instruction TLB miss exception\n"); - break; - } - break; case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ - switch (excp_model) { - case POWERPC_EXCP_602: - case POWERPC_EXCP_603: - case POWERPC_EXCP_603E: - case POWERPC_EXCP_G2: - goto tlb_miss_tgpr; - case POWERPC_EXCP_7x5: - goto tlb_miss; - case POWERPC_EXCP_74xx: - goto tlb_miss_74xx; - default: - cpu_abort(cs, "Invalid data load TLB miss exception\n"); - break; - } - break; case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ switch (excp_model) { case POWERPC_EXCP_602: case POWERPC_EXCP_603: case POWERPC_EXCP_603E: case POWERPC_EXCP_G2: - tlb_miss_tgpr: /* Swap temporary saved registers with GPRs */ if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { new_msr |= (target_ulong)1 << MSR_TGPR; hreg_swap_gpr_tgpr(env); } - goto tlb_miss; + /* fall through */ case POWERPC_EXCP_7x5: - tlb_miss: #if defined(DEBUG_SOFTWARE_TLB) if (qemu_log_enabled()) { const char *es; @@ -769,7 +737,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; break; case POWERPC_EXCP_74xx: - tlb_miss_74xx: #if defined(DEBUG_SOFTWARE_TLB) if (qemu_log_enabled()) { const char *es; @@ -799,7 +766,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) msr |= env->error_code; /* key bit */ break; default: - cpu_abort(cs, "Invalid data store TLB miss exception\n"); + cpu_abort(cs, "Invalid TLB miss exception\n"); break; } break; From patchwork Tue Jun 1 21:46:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabiano Rosas X-Patchwork-Id: 12292261 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2BD64C47080 for ; Tue, 1 Jun 2021 21:50:51 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 82A5F611CA for ; Tue, 1 Jun 2021 21:50:50 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 82A5F611CA Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.ibm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:53882 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1loCHh-0000Ns-Hw for qemu-devel@archiver.kernel.org; Tue, 01 Jun 2021 17:50:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33894) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1loCEC-0001xE-2V; Tue, 01 Jun 2021 17:47:12 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:48310) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1loCE8-0004Oa-Tg; Tue, 01 Jun 2021 17:47:11 -0400 Received: from pps.filterd (m0098417.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 151LYbWl063153; Tue, 1 Jun 2021 17:47:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=Duopp7ZnRxVjEbc4qWoAY8IaVuAaEgpQHqlrLEa89YE=; b=qQSoOb3P9tkZUxcnB90NGUCaYROREh8zXV+1Zg3ujBdzlfAas+XfnX97/8D02WWUldyb e0lVMhkBSvBch96UvG61zEU31Nos5fZC3Cbqv+Yyekf9iig4od/l6qtfnSj9INmVSD34 SHTkqRTHHWBGCy9dE3gfBqHfDmCGpTM5yI10PIKtqEH8BvJHF2a8Q9cKm7+K2n0umo0C qhsA3C5RWXXHFQDbtwAK4MSy2KHEoKrRXreeFr8ef3GD/82KwftnRC8R6nP7S2dbtrnA S97erKPoIATgnqpK8jzmPeeBxcUcN1TMq2O+1SyA/AwvhYJQFw5qUpI5T4emoxUPZDgp Fg== Received: from ppma03dal.us.ibm.com (b.bd.3ea9.ip4.static.sl-reverse.com [169.62.189.11]) by mx0a-001b2d01.pphosted.com with ESMTP id 38wu21u6ss-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 01 Jun 2021 17:47:03 -0400 Received: from pps.filterd (ppma03dal.us.ibm.com [127.0.0.1]) by ppma03dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 151LgoYW032033; Tue, 1 Jun 2021 21:47:02 GMT Received: from b03cxnp07029.gho.boulder.ibm.com (b03cxnp07029.gho.boulder.ibm.com [9.17.130.16]) by ppma03dal.us.ibm.com with ESMTP id 38ud8a1c5m-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 01 Jun 2021 21:47:02 +0000 Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp07029.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 151Ll1fM35324184 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 1 Jun 2021 21:47:01 GMT Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 74E557805F; Tue, 1 Jun 2021 21:47:01 +0000 (GMT) Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E4FF978064; Tue, 1 Jun 2021 21:46:59 +0000 (GMT) Received: from farosas.linux.ibm.com.com (unknown [9.211.142.192]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP; Tue, 1 Jun 2021 21:46:59 +0000 (GMT) From: Fabiano Rosas To: qemu-devel@nongnu.org Subject: [RFC PATCH 4/5] target/ppc: powerpc_excp: Standardize arguments to interrupt code Date: Tue, 1 Jun 2021 18:46:48 -0300 Message-Id: <20210601214649.785647-5-farosas@linux.ibm.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210601214649.785647-1-farosas@linux.ibm.com> References: <20210601214649.785647-1-farosas@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: pHv9LtJ-YAfGneT5dvQEn4-L7aixISes X-Proofpoint-ORIG-GUID: pHv9LtJ-YAfGneT5dvQEn4-L7aixISes X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.761 definitions=2021-06-01_10:2021-06-01, 2021-06-01 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 adultscore=0 clxscore=1015 priorityscore=1501 suspectscore=0 bulkscore=0 spamscore=0 phishscore=0 mlxlogscore=999 impostorscore=0 malwarescore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104190000 definitions=main-2106010143 Received-SPF: pass client-ip=148.163.158.5; envelope-from=farosas@linux.ibm.com; helo=mx0b-001b2d01.pphosted.com X-Spam_score_int: -19 X-Spam_score: -2.0 X-Spam_bar: -- X-Spam_report: (-2.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-ppc@nongnu.org, groug@kaod.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" The next patches will split the big switch statement in powerpc_excp into individual functions so it would be cleaner if all variables are already grouped in a structure and their names consistent. This patch makes it so that the old values for MSR and NIP (from env) are saved at the beginning as regs.msr and regs.nip and all modifications are done over this regs version. At the end of the function regs.msr and regs.nip are saved in the SRRs and regs.new_msr and regs.new_nip are written to env. There are two points of interest here: - The system call code has a particularity where it needs to use env->nip because it might return early and the modification needs to be seen by the virtual hypervisor hypercall code. I have added a comment making this clear. - The MSR filter at the beginning is being applied to the old MSR value only, i.e. the one that goes into SRR1. The new_msr is taken from env->msr without filtering the reserved bits. This might be a bug in the existing code. I'm also adding a comment to point that out. Signed-off-by: Fabiano Rosas --- target/ppc/excp_helper.c | 231 +++++++++++++++++++++------------------ 1 file changed, 125 insertions(+), 106 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index fd147e2a37..12bf829c8f 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -186,7 +186,7 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp, target_ulong msr, target_ulong *new_msr, - target_ulong *vector) + target_ulong *new_nip) { #if defined(TARGET_PPC64) CPUPPCState *env = &cpu->env; @@ -263,9 +263,9 @@ static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp, if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { if (ail == 2) { - *vector |= 0x0000000000018000ull; + *new_nip |= 0x0000000000018000ull; } else if (ail == 3) { - *vector |= 0xc000000000004000ull; + *new_nip |= 0xc000000000004000ull; } } else { /* @@ -273,15 +273,15 @@ static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp, * only the MSR. AIL=3 replaces the 0x17000 base with 0xc...3000. */ if (ail == 3) { - *vector &= ~0x0000000000017000ull; /* Un-apply the base offset */ - *vector |= 0xc000000000003000ull; /* Apply scv's AIL=3 offset */ + *new_nip &= ~0x0000000000017000ull; /* Un-apply the base offset */ + *new_nip |= 0xc000000000003000ull; /* Apply scv's AIL=3 offset */ } } #endif } -static inline void powerpc_set_excp_state(PowerPCCPU *cpu, - target_ulong vector, target_ulong msr) +static inline void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong new_nip, + target_ulong new_msr) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -294,9 +294,9 @@ static inline void powerpc_set_excp_state(PowerPCCPU *cpu, * will prevent setting of the HV bit which some exceptions might need * to do. */ - env->msr = msr & env->msr_mask; + env->msr = new_msr & env->msr_mask; hreg_compute_hflags(env); - env->nip = vector; + env->nip = new_nip; /* Reset exception state */ cs->exception_index = POWERPC_EXCP_NONE; env->error_code = 0; @@ -311,6 +311,17 @@ static inline void powerpc_set_excp_state(PowerPCCPU *cpu, check_tlb_flush(env, false); } +struct ppc_intr_args { + target_ulong nip; + target_ulong msr; + target_ulong new_nip; + target_ulong new_msr; + int sprn_srr0; + int sprn_srr1; + int sprn_asrr0; + int sprn_asrr1; +}; + /* * Note that this function should be greatly optimized when called * with a constant excp, from ppc_hw_interrupt @@ -319,37 +330,40 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; - target_ulong msr, new_msr, vector; - int srr0, srr1, asrr0, asrr1, lev = -1; + struct ppc_intr_args regs; + int lev = -1; qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx " => %08x (%02x)\n", env->nip, excp, env->error_code); /* new srr1 value excluding must-be-zero bits */ if (excp_model == POWERPC_EXCP_BOOKE) { - msr = env->msr; + regs.msr = env->msr; } else { - msr = env->msr & ~0x783f0000ULL; + regs.msr = env->msr & ~0x783f0000ULL; } + regs.nip = env->nip; /* * new interrupt handler msr preserves existing HV and ME unless * explicitly overriden + * + * XXX: should this use the filtered MSR (regs.msr) from above + * instead of the unfiltered env->msr? */ - new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); + regs.new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); - /* target registers */ - srr0 = SPR_SRR0; - srr1 = SPR_SRR1; - asrr0 = -1; - asrr1 = -1; + regs.sprn_srr0 = SPR_SRR0; + regs.sprn_srr1 = SPR_SRR1; + regs.sprn_asrr0 = -1; + regs.sprn_asrr1 = -1; /* * check for special resume at 0x100 from doze/nap/sleep/winkle on * P7/P8/P9 */ if (env->resume_as_sreset) { - excp = powerpc_reset_wakeup(cs, env, excp, &msr); + excp = powerpc_reset_wakeup(cs, env, excp, ®s.msr); } /* @@ -373,12 +387,12 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) case POWERPC_EXCP_CRITICAL: /* Critical input */ switch (excp_model) { case POWERPC_EXCP_40x: - srr0 = SPR_40x_SRR2; - srr1 = SPR_40x_SRR3; + regs.sprn_srr0 = SPR_40x_SRR2; + regs.sprn_srr1 = SPR_40x_SRR3; break; case POWERPC_EXCP_BOOKE: - srr0 = SPR_BOOKE_CSRR0; - srr1 = SPR_BOOKE_CSRR1; + regs.sprn_srr0 = SPR_BOOKE_CSRR0; + regs.sprn_srr1 = SPR_BOOKE_CSRR1; break; case POWERPC_EXCP_G2: break; @@ -406,24 +420,24 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) * ISA specifies HV, but can be delivered to guest with HV * clear (e.g., see FWNMI in PAPR). */ - new_msr |= (target_ulong)MSR_HVB; + regs.new_msr |= (target_ulong)MSR_HVB; } /* machine check exceptions don't have ME set */ - new_msr &= ~((target_ulong)1 << MSR_ME); + regs.new_msr &= ~((target_ulong)1 << MSR_ME); /* XXX: should also have something loaded in DAR / DSISR */ switch (excp_model) { case POWERPC_EXCP_40x: - srr0 = SPR_40x_SRR2; - srr1 = SPR_40x_SRR3; + regs.sprn_srr0 = SPR_40x_SRR2; + regs.sprn_srr1 = SPR_40x_SRR3; break; case POWERPC_EXCP_BOOKE: /* FIXME: choose one or the other based on CPU type */ - srr0 = SPR_BOOKE_MCSRR0; - srr1 = SPR_BOOKE_MCSRR1; - asrr0 = SPR_BOOKE_CSRR0; - asrr1 = SPR_BOOKE_CSRR1; + regs.sprn_srr0 = SPR_BOOKE_MCSRR0; + regs.sprn_srr1 = SPR_BOOKE_MCSRR1; + regs.sprn_asrr0 = SPR_BOOKE_CSRR0; + regs.sprn_asrr1 = SPR_BOOKE_CSRR1; break; default: break; @@ -435,8 +449,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) break; case POWERPC_EXCP_ISI: /* Instruction storage exception */ LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx - "\n", msr, env->nip); - msr |= env->error_code; + "\n", regs.msr, regs.nip); + regs.msr |= env->error_code; break; case POWERPC_EXCP_EXTERNAL: /* External input */ { @@ -466,10 +480,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } if (!lpes0) { - new_msr |= (target_ulong)MSR_HVB; - new_msr |= env->msr & ((target_ulong)1 << MSR_RI); - srr0 = SPR_HSRR0; - srr1 = SPR_HSRR1; + regs.new_msr |= (target_ulong)MSR_HVB; + regs.new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + regs.sprn_srr0 = SPR_HSRR0; + regs.sprn_srr1 = SPR_HSRR1; } if (env->mpic_proxy) { /* IACK the IRQ on delivery */ @@ -501,20 +515,20 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) * instruction, so always use store_next and claim we are * precise in the MSR. */ - msr |= 0x00100000; + regs.msr |= 0x00100000; env->spr[SPR_BOOKE_ESR] = ESR_FP; break; case POWERPC_EXCP_INVAL: - LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip); - msr |= 0x00080000; + LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", regs.nip); + regs.msr |= 0x00080000; env->spr[SPR_BOOKE_ESR] = ESR_PIL; break; case POWERPC_EXCP_PRIV: - msr |= 0x00040000; + regs.msr |= 0x00040000; env->spr[SPR_BOOKE_ESR] = ESR_PPR; break; case POWERPC_EXCP_TRAP: - msr |= 0x00020000; + regs.msr |= 0x00020000; env->spr[SPR_BOOKE_ESR] = ESR_PTR; break; default: @@ -535,9 +549,12 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) /* * We need to correct the NIP which in this case is supposed - * to point to the next instruction + * to point to the next instruction. We also set env->nip here + * because the modification needs to be accessible by the + * virtual hypervisor code below. */ - env->nip += 4; + regs.nip += 4; + env->nip = regs.nip; /* "PAPR mode" built-in hypercall emulation */ if ((lev == 1) && cpu->vhyp) { @@ -546,16 +563,17 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) vhc->hypercall(cpu->vhyp, cpu); return; } + if (lev == 1) { - new_msr |= (target_ulong)MSR_HVB; + regs.new_msr |= (target_ulong)MSR_HVB; } break; case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ lev = env->error_code; dump_syscall(env); - env->nip += 4; - new_msr |= env->msr & ((target_ulong)1 << MSR_EE); - new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + regs.nip += 4; + regs.new_msr |= env->msr & ((target_ulong)1 << MSR_EE); + regs.new_msr |= env->msr & ((target_ulong)1 << MSR_RI); break; case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ @@ -569,8 +587,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) LOG_EXCP("WDT exception\n"); switch (excp_model) { case POWERPC_EXCP_BOOKE: - srr0 = SPR_BOOKE_CSRR0; - srr1 = SPR_BOOKE_CSRR1; + regs.sprn_srr0 = SPR_BOOKE_CSRR0; + regs.sprn_srr1 = SPR_BOOKE_CSRR1; break; default: break; @@ -582,10 +600,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) case POWERPC_EXCP_DEBUG: /* Debug interrupt */ if (env->flags & POWERPC_FLAG_DE) { /* FIXME: choose one or the other based on CPU type */ - srr0 = SPR_BOOKE_DSRR0; - srr1 = SPR_BOOKE_DSRR1; - asrr0 = SPR_BOOKE_CSRR0; - asrr1 = SPR_BOOKE_CSRR1; + regs.sprn_srr0 = SPR_BOOKE_DSRR0; + regs.sprn_srr1 = SPR_BOOKE_DSRR1; + regs.sprn_asrr0 = SPR_BOOKE_CSRR0; + regs.sprn_asrr1 = SPR_BOOKE_CSRR1; /* DBSR already modified by caller */ } else { cpu_abort(cs, "Debug exception triggered on unsupported model\n"); @@ -614,22 +632,22 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ break; case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ - srr0 = SPR_BOOKE_CSRR0; - srr1 = SPR_BOOKE_CSRR1; + regs.sprn_srr0 = SPR_BOOKE_CSRR0; + regs.sprn_srr1 = SPR_BOOKE_CSRR1; break; case POWERPC_EXCP_RESET: /* System reset exception */ /* A power-saving exception sets ME, otherwise it is unchanged */ if (msr_pow) { /* indicate that we resumed from power save mode */ - msr |= 0x10000; - new_msr |= ((target_ulong)1 << MSR_ME); + regs.msr |= 0x10000; + regs.new_msr |= ((target_ulong)1 << MSR_ME); } if (env->msr_mask & MSR_HVB) { /* * ISA specifies HV, but can be delivered to guest with HV * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU). */ - new_msr |= (target_ulong)MSR_HVB; + regs.new_msr |= (target_ulong)MSR_HVB; } else { if (msr_pow) { cpu_abort(cs, "Trying to deliver power-saving system reset " @@ -642,7 +660,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) case POWERPC_EXCP_TRACE: /* Trace exception */ break; case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ - msr |= env->error_code; + regs.msr |= env->error_code; /* fall through */ case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ @@ -651,10 +669,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ case POWERPC_EXCP_HV_EMU: case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ - srr0 = SPR_HSRR0; - srr1 = SPR_HSRR1; - new_msr |= (target_ulong)MSR_HVB; - new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + regs.sprn_srr0 = SPR_HSRR0; + regs.sprn_srr1 = SPR_HSRR1; + regs.new_msr |= (target_ulong)MSR_HVB; + regs.new_msr |= env->msr & ((target_ulong)1 << MSR_RI); break; case POWERPC_EXCP_VPU: /* Vector unavailable exception */ case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ @@ -666,10 +684,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */ #ifdef TARGET_PPC64 env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); - srr0 = SPR_HSRR0; - srr1 = SPR_HSRR1; - new_msr |= (target_ulong)MSR_HVB; - new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + regs.sprn_srr0 = SPR_HSRR0; + regs.sprn_srr1 = SPR_HSRR1; + regs.new_msr |= (target_ulong)MSR_HVB; + regs.new_msr |= env->msr & ((target_ulong)1 << MSR_RI); #endif break; case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ @@ -697,8 +715,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) case POWERPC_EXCP_603E: case POWERPC_EXCP_G2: /* Swap temporary saved registers with GPRs */ - if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { - new_msr |= (target_ulong)1 << MSR_TGPR; + if (!(regs.new_msr & ((target_ulong)1 << MSR_TGPR))) { + regs.new_msr |= (target_ulong)1 << MSR_TGPR; hreg_swap_gpr_tgpr(env); } /* fall through */ @@ -731,10 +749,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) env->error_code); } #endif - msr |= env->crf[0] << 28; - msr |= env->error_code; /* key, D/I, S/L bits */ + regs.msr |= env->crf[0] << 28; + regs.msr |= env->error_code; /* key, D/I, S/L bits */ /* Set way using a LRU mechanism */ - msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; + regs.msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; break; case POWERPC_EXCP_74xx: #if defined(DEBUG_SOFTWARE_TLB) @@ -763,7 +781,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) env->error_code); } #endif - msr |= env->error_code; /* key bit */ + regs.msr |= env->error_code; /* key bit */ break; default: cpu_abort(cs, "Invalid TLB miss exception\n"); @@ -829,11 +847,11 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) /* Sanity check */ if (!(env->msr_mask & MSR_HVB)) { - if (new_msr & MSR_HVB) { + if (regs.new_msr & MSR_HVB) { cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with " "no HV support\n", excp); } - if (srr0 == SPR_HSRR0) { + if (regs.sprn_srr0 == SPR_HSRR0) { cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with " "no HV support\n", excp); } @@ -845,88 +863,89 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) */ #ifdef TARGET_PPC64 if (excp_model == POWERPC_EXCP_POWER7) { - if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) { - new_msr |= (target_ulong)1 << MSR_LE; + if (!(regs.new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) { + regs.new_msr |= (target_ulong)1 << MSR_LE; } } else if (excp_model == POWERPC_EXCP_POWER8) { - if (new_msr & MSR_HVB) { + if (regs.new_msr & MSR_HVB) { if (env->spr[SPR_HID0] & HID0_HILE) { - new_msr |= (target_ulong)1 << MSR_LE; + regs.new_msr |= (target_ulong)1 << MSR_LE; } } else if (env->spr[SPR_LPCR] & LPCR_ILE) { - new_msr |= (target_ulong)1 << MSR_LE; + regs.new_msr |= (target_ulong)1 << MSR_LE; } } else if (excp_model == POWERPC_EXCP_POWER9 || excp_model == POWERPC_EXCP_POWER10) { - if (new_msr & MSR_HVB) { + if (regs.new_msr & MSR_HVB) { if (env->spr[SPR_HID0] & HID0_POWER9_HILE) { - new_msr |= (target_ulong)1 << MSR_LE; + regs.new_msr |= (target_ulong)1 << MSR_LE; } } else if (env->spr[SPR_LPCR] & LPCR_ILE) { - new_msr |= (target_ulong)1 << MSR_LE; + regs.new_msr |= (target_ulong)1 << MSR_LE; } } else if (msr_ile) { - new_msr |= (target_ulong)1 << MSR_LE; + regs.new_msr |= (target_ulong)1 << MSR_LE; } #else if (msr_ile) { - new_msr |= (target_ulong)1 << MSR_LE; + regs.new_msr |= (target_ulong)1 << MSR_LE; } #endif - vector = env->excp_vectors[excp]; - if (vector == (target_ulong)-1ULL) { + regs.new_nip = env->excp_vectors[excp]; + if (regs.new_nip == (target_ulong)-1ULL) { cpu_abort(cs, "Raised an exception without defined vector %d\n", excp); } - vector |= env->excp_prefix; + regs.new_nip |= env->excp_prefix; /* If any alternate SRR register are defined, duplicate saved values */ - if (asrr0 != -1) { - env->spr[asrr0] = env->nip; + if (regs.sprn_asrr0 != -1) { + env->spr[regs.sprn_asrr0] = regs.nip; } - if (asrr1 != -1) { - env->spr[asrr1] = msr; + if (regs.sprn_asrr1 != -1) { + env->spr[regs.sprn_asrr1] = regs.msr; } #if defined(TARGET_PPC64) if (excp_model == POWERPC_EXCP_BOOKE) { if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */ - new_msr |= (target_ulong)1 << MSR_CM; + regs.new_msr |= (target_ulong)1 << MSR_CM; } else { - vector = (uint32_t)vector; + regs.new_nip = (uint32_t)regs.new_nip; } } else { if (!msr_isf && !mmu_is_64bit(env->mmu_model)) { - vector = (uint32_t)vector; + regs.new_nip = (uint32_t)regs.new_nip; } else { - new_msr |= (target_ulong)1 << MSR_SF; + regs.new_msr |= (target_ulong)1 << MSR_SF; } } #endif if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { /* Save PC */ - env->spr[srr0] = env->nip; + env->spr[regs.sprn_srr0] = regs.nip; /* Save MSR */ - env->spr[srr1] = msr; + env->spr[regs.sprn_srr1] = regs.msr; #if defined(TARGET_PPC64) } else { - vector += lev * 0x20; + regs.new_nip += lev * 0x20; - env->lr = env->nip; - env->ctr = msr; + env->lr = regs.nip; + env->ctr = regs.msr; #endif } - /* This can update new_msr and vector if AIL applies */ - ppc_excp_apply_ail(cpu, excp_model, excp, msr, &new_msr, &vector); + /* This can update regs.new_msr and regs.new_nip if AIL applies */ + ppc_excp_apply_ail(cpu, excp_model, excp, regs.msr, ®s.new_msr, + ®s.new_nip); - powerpc_set_excp_state(cpu, vector, new_msr); + powerpc_set_excp_state(cpu, regs.new_nip, regs.new_msr); } void ppc_cpu_do_interrupt(CPUState *cs) From patchwork Tue Jun 1 21:46:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabiano Rosas X-Patchwork-Id: 12292259 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8852BC47080 for ; Tue, 1 Jun 2021 21:49:19 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 848FB6101B for ; Tue, 1 Jun 2021 21:49:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 848FB6101B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.ibm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:48704 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1loCGD-0005Mt-Gd for qemu-devel@archiver.kernel.org; Tue, 01 Jun 2021 17:49:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34000) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1loCER-0002MG-7T; Tue, 01 Jun 2021 17:47:27 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:22878) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1loCEJ-0004WY-3J; Tue, 01 Jun 2021 17:47:26 -0400 Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 151LkgW4022203; Tue, 1 Jun 2021 17:47:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=jtkU5B9IlC8qznx0S2rVcuBIqTGipLbxWK5bagqwQRs=; b=cZgKh1eRE9oU/J9H8Z7WY1MNRdrRcLeo3IqV+AuV3aFo9t6U9PQ6UEL0DAaFHQMILf2Y qxn0zOGeXaCks6E0r+PlUKNSBddYuHed6VfqyExiwpaW2tE7iAr1m53Qj+qMjCpcrZ5N PG/nCYK6kFFVo8GMcjPg7m0SzUBMiaM/W/zvBsZpLFWSOc1DXdTJK78D6SbG7SPipglc bnZAxy1W4cVHni2DVsMgdpYeR3IGAbrGPu8EkryxyUBi6kZoYmziLbLSpNahjjyfxdFQ k7tFqQnqFKq7oqdHO+IHuWiwZpDMn5cTCdt9wXqYkwxv40lSdDYg3I86H5dgM/Wtt03s CQ== Received: from ppma01wdc.us.ibm.com (fd.55.37a9.ip4.static.sl-reverse.com [169.55.85.253]) by mx0a-001b2d01.pphosted.com with ESMTP id 38ww3xr04f-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 01 Jun 2021 17:47:05 -0400 Received: from pps.filterd (ppma01wdc.us.ibm.com [127.0.0.1]) by ppma01wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 151LgMWd003370; Tue, 1 Jun 2021 21:47:04 GMT Received: from b03cxnp08026.gho.boulder.ibm.com (b03cxnp08026.gho.boulder.ibm.com [9.17.130.18]) by ppma01wdc.us.ibm.com with ESMTP id 38ud892qg8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 01 Jun 2021 21:47:04 +0000 Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp08026.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 151Ll3P128442946 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 1 Jun 2021 21:47:03 GMT Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 9C00478060; Tue, 1 Jun 2021 21:47:03 +0000 (GMT) Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D7D007805F; Tue, 1 Jun 2021 21:47:01 +0000 (GMT) Received: from farosas.linux.ibm.com.com (unknown [9.211.142.192]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP; Tue, 1 Jun 2021 21:47:01 +0000 (GMT) From: Fabiano Rosas To: qemu-devel@nongnu.org Subject: [RFC PATCH 5/5] target/ppc: powerpc_excp: Move interrupt raising code to QOM Date: Tue, 1 Jun 2021 18:46:49 -0300 Message-Id: <20210601214649.785647-6-farosas@linux.ibm.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210601214649.785647-1-farosas@linux.ibm.com> References: <20210601214649.785647-1-farosas@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: qDgOqg3HRXQkZqdOZ7M6AT0o1df4L6wX X-Proofpoint-ORIG-GUID: qDgOqg3HRXQkZqdOZ7M6AT0o1df4L6wX X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.391, 18.0.761 definitions=2021-06-01_10:2021-06-01, 2021-06-01 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 lowpriorityscore=0 bulkscore=0 mlxlogscore=999 phishscore=0 clxscore=1015 malwarescore=0 mlxscore=0 suspectscore=0 adultscore=0 priorityscore=1501 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2104190000 definitions=main-2106010143 Received-SPF: pass client-ip=148.163.156.1; envelope-from=farosas@linux.ibm.com; helo=mx0a-001b2d01.pphosted.com X-Spam_score_int: -19 X-Spam_score: -2.0 X-Spam_bar: -- X-Spam_report: (-2.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-ppc@nongnu.org, groug@kaod.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This patch introduces a new way to dispatch the emulated interrupts in powerpc_excp. It leverages the QEMU object model to store the implementations for each interrupt and link them to their identifier from POWERPC_EXCP enum. The processor-specific code then uses this identifier to register which interrupts it supports. Interrupts now come out of the big switch in powerpc_excp into their own functions: static void ppc_intr_system_reset() { /* * Interrupt code. Sets any specific registers and MSR bits. */ } PPC_DEFINE_INTR(POWERPC_EXCP_RESET, system_reset, "System reset"); ^This line registers the interrupt with QOM. When we initialize the emulated processor, the correct set of interrupts is instantiated (pretty much like we already do): static void init_excp_POWER9(CPUPPCState *env) { ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); (...) } When it comes the time to inject the interrupt: static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) { (...) intr = &env->entry_points[excp]; intr->setup_regs(); <-- ppc_intr_system_reset function (...) env->spr[srr0] = nip; env->spr[srr1] = msr; env->nip = intr->addr; env->msr = new_msr; } Some points to notice: - The structure for the new PPCInterrupt class object is stored directly inside of CPUPPCState (env) so the translation code can still access it linearly at an offset. - Some interrupts were being registered for P7/8/9/10 but were never implemented (i.e. not in the powerpc_excp switch statement). They are likely never triggered. We now get the benefit of QOM warning in such cases: qemu-system-ppc64: missing object type 'POWERPC_EXCP_SDOOR' qemu-system-ppc64: missing object type 'POWERPC_EXCP_HV_MAINT' - The code currently allows for Program interrupts to be ignored and System call interrupts to be directed to the vhyp hypercall code. I have added an 'ignore' flag to deal with these two cases and return early from powerpc_excp. Signed-off-by: Fabiano Rosas --- target/ppc/cpu.h | 29 +- target/ppc/cpu_init.c | 640 +++++++++++++++++++-------------------- target/ppc/excp_helper.c | 545 ++------------------------------- target/ppc/interrupts.c | 638 ++++++++++++++++++++++++++++++++++++++ target/ppc/machine.c | 2 +- target/ppc/meson.build | 1 + target/ppc/ppc_intr.h | 55 ++++ target/ppc/translate.c | 3 +- 8 files changed, 1066 insertions(+), 847 deletions(-) create mode 100644 target/ppc/interrupts.c create mode 100644 target/ppc/ppc_intr.h diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index b0934d9be4..012677965f 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -174,6 +174,33 @@ enum { POWERPC_EXCP_TRAP = 0x40, }; +typedef struct PPCInterrupt PPCInterrupt; +typedef struct ppc_intr_args ppc_intr_args; +typedef void (*ppc_intr_fn_t)(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore); + +struct ppc_intr_args { + target_ulong nip; + target_ulong msr; + target_ulong new_nip; + target_ulong new_msr; + int sprn_srr0; + int sprn_srr1; + int sprn_asrr0; + int sprn_asrr1; + int lev; +}; + +struct PPCInterrupt { + Object parent; + + int id; + const char *name; + target_ulong addr; + ppc_intr_fn_t setup_regs; +}; + #define PPC_INPUT(env) ((env)->bus_model) /*****************************************************************************/ @@ -1115,7 +1142,7 @@ struct CPUPPCState { uint32_t irq_input_state; void **irq_inputs; - target_ulong excp_vectors[POWERPC_EXCP_NB]; /* Exception vectors */ + PPCInterrupt entry_points[POWERPC_EXCP_NB]; target_ulong excp_prefix; target_ulong ivor_mask; target_ulong ivpr_mask; diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index d0411e7302..d91183357d 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -46,6 +46,7 @@ #include "helper_regs.h" #include "internal.h" #include "spr_tcg.h" +#include "ppc_intr.h" /* #define PPC_DEBUG_SPR */ /* #define USE_APPLE_GDB */ @@ -2132,16 +2133,16 @@ static void register_8xx_sprs(CPUPPCState *env) static void init_excp_4xx_real(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_PIT] = 0x00001000; - env->excp_vectors[POWERPC_EXCP_FIT] = 0x00001010; - env->excp_vectors[POWERPC_EXCP_WDT] = 0x00001020; - env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00002000; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_CRITICAL); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00001000, POWERPC_EXCP_PIT); + ppc_intr_add(env, 0x00001010, POWERPC_EXCP_FIT); + ppc_intr_add(env, 0x00001020, POWERPC_EXCP_WDT); + ppc_intr_add(env, 0x00002000, POWERPC_EXCP_DEBUG); env->ivor_mask = 0x0000FFF0UL; env->ivpr_mask = 0xFFFF0000UL; /* Hardware reset vector */ @@ -2152,20 +2153,20 @@ static void init_excp_4xx_real(CPUPPCState *env) static void init_excp_4xx_softmmu(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_PIT] = 0x00001000; - env->excp_vectors[POWERPC_EXCP_FIT] = 0x00001010; - env->excp_vectors[POWERPC_EXCP_WDT] = 0x00001020; - env->excp_vectors[POWERPC_EXCP_DTLB] = 0x00001100; - env->excp_vectors[POWERPC_EXCP_ITLB] = 0x00001200; - env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00002000; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_CRITICAL); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00001000, POWERPC_EXCP_PIT); + ppc_intr_add(env, 0x00001010, POWERPC_EXCP_FIT); + ppc_intr_add(env, 0x00001020, POWERPC_EXCP_WDT); + ppc_intr_add(env, 0x00001100, POWERPC_EXCP_DTLB); + ppc_intr_add(env, 0x00001200, POWERPC_EXCP_ITLB); + ppc_intr_add(env, 0x00002000, POWERPC_EXCP_DEBUG); env->ivor_mask = 0x0000FFF0UL; env->ivpr_mask = 0xFFFF0000UL; /* Hardware reset vector */ @@ -2176,21 +2177,21 @@ static void init_excp_4xx_softmmu(CPUPPCState *env) static void init_excp_MPC5xx(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_FPA] = 0x00000E00; - env->excp_vectors[POWERPC_EXCP_EMUL] = 0x00001000; - env->excp_vectors[POWERPC_EXCP_DABR] = 0x00001C00; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001C00; - env->excp_vectors[POWERPC_EXCP_MEXTBR] = 0x00001E00; - env->excp_vectors[POWERPC_EXCP_NMEXTBR] = 0x00001F00; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00000E00, POWERPC_EXCP_FPA); + ppc_intr_add(env, 0x00001000, POWERPC_EXCP_EMUL); + ppc_intr_add(env, 0x00001C00, POWERPC_EXCP_DABR); + ppc_intr_add(env, 0x00001C00, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001E00, POWERPC_EXCP_MEXTBR); + ppc_intr_add(env, 0x00001F00, POWERPC_EXCP_NMEXTBR); env->ivor_mask = 0x0000FFF0UL; env->ivpr_mask = 0xFFFF0000UL; /* Hardware reset vector */ @@ -2201,27 +2202,27 @@ static void init_excp_MPC5xx(CPUPPCState *env) static void init_excp_MPC8xx(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_FPA] = 0x00000E00; - env->excp_vectors[POWERPC_EXCP_EMUL] = 0x00001000; - env->excp_vectors[POWERPC_EXCP_ITLB] = 0x00001100; - env->excp_vectors[POWERPC_EXCP_DTLB] = 0x00001200; - env->excp_vectors[POWERPC_EXCP_ITLBE] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_DTLBE] = 0x00001400; - env->excp_vectors[POWERPC_EXCP_DABR] = 0x00001C00; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001C00; - env->excp_vectors[POWERPC_EXCP_MEXTBR] = 0x00001E00; - env->excp_vectors[POWERPC_EXCP_NMEXTBR] = 0x00001F00; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00000E00, POWERPC_EXCP_FPA); + ppc_intr_add(env, 0x00001000, POWERPC_EXCP_EMUL); + ppc_intr_add(env, 0x00001100, POWERPC_EXCP_ITLB); + ppc_intr_add(env, 0x00001200, POWERPC_EXCP_DTLB); + ppc_intr_add(env, 0x00001300, POWERPC_EXCP_ITLBE); + ppc_intr_add(env, 0x00001400, POWERPC_EXCP_DTLBE); + ppc_intr_add(env, 0x00001C00, POWERPC_EXCP_DABR); + ppc_intr_add(env, 0x00001C00, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001E00, POWERPC_EXCP_MEXTBR); + ppc_intr_add(env, 0x00001F00, POWERPC_EXCP_NMEXTBR); env->ivor_mask = 0x0000FFF0UL; env->ivpr_mask = 0xFFFF0000UL; /* Hardware reset vector */ @@ -2232,23 +2233,23 @@ static void init_excp_MPC8xx(CPUPPCState *env) static void init_excp_G2(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000A00; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_IFTLB] = 0x00001000; - env->excp_vectors[POWERPC_EXCP_DLTLB] = 0x00001100; - env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000A00, POWERPC_EXCP_CRITICAL); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00001000, POWERPC_EXCP_IFTLB); + ppc_intr_add(env, 0x00001100, POWERPC_EXCP_DLTLB); + ppc_intr_add(env, 0x00001200, POWERPC_EXCP_DSTLB); + ppc_intr_add(env, 0x00001300, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001400, POWERPC_EXCP_SMI); /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2257,26 +2258,26 @@ static void init_excp_G2(CPUPPCState *env) static void init_excp_e200(CPUPPCState *env, target_ulong ivpr_mask) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000FFC; - env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_APU] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_FIT] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_WDT] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_DTLB] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_ITLB] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_SPEU] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_EFPDI] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_EFPRI] = 0x00000000; + ppc_intr_add(env, 0x00000FFC, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_CRITICAL); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_APU); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_FIT); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_WDT); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_DTLB); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_ITLB); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_DEBUG); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_SPEU); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_EFPDI); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_EFPRI); env->ivor_mask = 0x0000FFF7UL; env->ivpr_mask = ivpr_mask; /* Hardware reset vector */ @@ -2287,22 +2288,22 @@ static void init_excp_e200(CPUPPCState *env, target_ulong ivpr_mask) static void init_excp_BookE(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_APU] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_FIT] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_WDT] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_DTLB] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_ITLB] = 0x00000000; - env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00000000; + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_CRITICAL); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_APU); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_FIT); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_WDT); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_DTLB); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_ITLB); + ppc_intr_add(env, 0x00000000, POWERPC_EXCP_DEBUG); env->ivor_mask = 0x0000FFF0UL; env->ivpr_mask = 0xFFFF0000UL; /* Hardware reset vector */ @@ -2313,18 +2314,18 @@ static void init_excp_BookE(CPUPPCState *env) static void init_excp_601(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_IO] = 0x00000A00; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_RUNM] = 0x00002000; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000A00, POWERPC_EXCP_IO); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00002000, POWERPC_EXCP_RUNM); /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2334,24 +2335,24 @@ static void init_excp_602(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) /* XXX: exception prefix has a special behavior on 602 */ - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_IFTLB] = 0x00001000; - env->excp_vectors[POWERPC_EXCP_DLTLB] = 0x00001100; - env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; - env->excp_vectors[POWERPC_EXCP_WDT] = 0x00001500; - env->excp_vectors[POWERPC_EXCP_EMUL] = 0x00001600; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00001000, POWERPC_EXCP_IFTLB); + ppc_intr_add(env, 0x00001100, POWERPC_EXCP_DLTLB); + ppc_intr_add(env, 0x00001200, POWERPC_EXCP_DSTLB); + ppc_intr_add(env, 0x00001300, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001400, POWERPC_EXCP_SMI); + ppc_intr_add(env, 0x00001500, POWERPC_EXCP_WDT); + ppc_intr_add(env, 0x00001600, POWERPC_EXCP_EMUL); /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2360,22 +2361,22 @@ static void init_excp_602(CPUPPCState *env) static void init_excp_603(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_IFTLB] = 0x00001000; - env->excp_vectors[POWERPC_EXCP_DLTLB] = 0x00001100; - env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00001000, POWERPC_EXCP_IFTLB); + ppc_intr_add(env, 0x00001100, POWERPC_EXCP_DLTLB); + ppc_intr_add(env, 0x00001200, POWERPC_EXCP_DSTLB); + ppc_intr_add(env, 0x00001300, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001400, POWERPC_EXCP_SMI); /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2384,20 +2385,20 @@ static void init_excp_603(CPUPPCState *env) static void init_excp_604(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00000F00, POWERPC_EXCP_PERFM); + ppc_intr_add(env, 0x00001300, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001400, POWERPC_EXCP_SMI); /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2406,21 +2407,21 @@ static void init_excp_604(CPUPPCState *env) static void init_excp_7x0(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; - env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00000F00, POWERPC_EXCP_PERFM); + ppc_intr_add(env, 0x00001300, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001400, POWERPC_EXCP_SMI); + ppc_intr_add(env, 0x00001700, POWERPC_EXCP_THERM); /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2429,20 +2430,20 @@ static void init_excp_7x0(CPUPPCState *env) static void init_excp_750cl(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00000F00, POWERPC_EXCP_PERFM); + ppc_intr_add(env, 0x00001300, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001400, POWERPC_EXCP_SMI); /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2451,20 +2452,20 @@ static void init_excp_750cl(CPUPPCState *env) static void init_excp_750cx(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00000F00, POWERPC_EXCP_PERFM); + ppc_intr_add(env, 0x00001300, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001700, POWERPC_EXCP_THERM); /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2474,24 +2475,24 @@ static void init_excp_750cx(CPUPPCState *env) static void init_excp_7x5(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00; - env->excp_vectors[POWERPC_EXCP_IFTLB] = 0x00001000; - env->excp_vectors[POWERPC_EXCP_DLTLB] = 0x00001100; - env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; - env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00000F00, POWERPC_EXCP_PERFM); + ppc_intr_add(env, 0x00001000, POWERPC_EXCP_IFTLB); + ppc_intr_add(env, 0x00001100, POWERPC_EXCP_DLTLB); + ppc_intr_add(env, 0x00001200, POWERPC_EXCP_DSTLB); + ppc_intr_add(env, 0x00001300, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001400, POWERPC_EXCP_SMI); + ppc_intr_add(env, 0x00001700, POWERPC_EXCP_THERM); /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2500,23 +2501,23 @@ static void init_excp_7x5(CPUPPCState *env) static void init_excp_7400(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00; - env->excp_vectors[POWERPC_EXCP_VPU] = 0x00000F20; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; - env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001600; - env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00000F00, POWERPC_EXCP_PERFM); + ppc_intr_add(env, 0x00000F20, POWERPC_EXCP_VPU); + ppc_intr_add(env, 0x00001300, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001400, POWERPC_EXCP_SMI); + ppc_intr_add(env, 0x00001600, POWERPC_EXCP_VPUA); + ppc_intr_add(env, 0x00001700, POWERPC_EXCP_THERM); /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2525,25 +2526,25 @@ static void init_excp_7400(CPUPPCState *env) static void init_excp_7450(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00; - env->excp_vectors[POWERPC_EXCP_VPU] = 0x00000F20; - env->excp_vectors[POWERPC_EXCP_IFTLB] = 0x00001000; - env->excp_vectors[POWERPC_EXCP_DLTLB] = 0x00001100; - env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400; - env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001600; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00000F00, POWERPC_EXCP_PERFM); + ppc_intr_add(env, 0x00000F20, POWERPC_EXCP_VPU); + ppc_intr_add(env, 0x00001000, POWERPC_EXCP_IFTLB); + ppc_intr_add(env, 0x00001100, POWERPC_EXCP_DLTLB); + ppc_intr_add(env, 0x00001200, POWERPC_EXCP_DSTLB); + ppc_intr_add(env, 0x00001300, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001400, POWERPC_EXCP_SMI); + ppc_intr_add(env, 0x00001600, POWERPC_EXCP_VPUA); /* Hardware reset vector */ env->hreset_vector = 0x00000100UL; #endif @@ -2553,26 +2554,26 @@ static void init_excp_7450(CPUPPCState *env) static void init_excp_970(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_DSEG] = 0x00000380; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_ISEG] = 0x00000480; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_HDECR] = 0x00000980; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00; - env->excp_vectors[POWERPC_EXCP_VPU] = 0x00000F20; - env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300; - env->excp_vectors[POWERPC_EXCP_MAINT] = 0x00001600; - env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001700; - env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001800; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000380, POWERPC_EXCP_DSEG); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000480, POWERPC_EXCP_ISEG); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000980, POWERPC_EXCP_HDECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00000F00, POWERPC_EXCP_PERFM); + ppc_intr_add(env, 0x00000F20, POWERPC_EXCP_VPU); + ppc_intr_add(env, 0x00001300, POWERPC_EXCP_IABR); + ppc_intr_add(env, 0x00001600, POWERPC_EXCP_MAINT); + ppc_intr_add(env, 0x00001700, POWERPC_EXCP_VPUA); + ppc_intr_add(env, 0x00001800, POWERPC_EXCP_THERM); /* Hardware reset vector */ env->hreset_vector = 0x0000000000000100ULL; #endif @@ -2581,27 +2582,27 @@ static void init_excp_970(CPUPPCState *env) static void init_excp_POWER7(CPUPPCState *env) { #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100; - env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200; - env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300; - env->excp_vectors[POWERPC_EXCP_DSEG] = 0x00000380; - env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400; - env->excp_vectors[POWERPC_EXCP_ISEG] = 0x00000480; - env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500; - env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600; - env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700; - env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800; - env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900; - env->excp_vectors[POWERPC_EXCP_HDECR] = 0x00000980; - env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00; - env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00; - env->excp_vectors[POWERPC_EXCP_HDSI] = 0x00000E00; - env->excp_vectors[POWERPC_EXCP_HISI] = 0x00000E20; - env->excp_vectors[POWERPC_EXCP_HV_EMU] = 0x00000E40; - env->excp_vectors[POWERPC_EXCP_HV_MAINT] = 0x00000E60; - env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00; - env->excp_vectors[POWERPC_EXCP_VPU] = 0x00000F20; - env->excp_vectors[POWERPC_EXCP_VSXU] = 0x00000F40; + ppc_intr_add(env, 0x00000100, POWERPC_EXCP_RESET); + ppc_intr_add(env, 0x00000200, POWERPC_EXCP_MCHECK); + ppc_intr_add(env, 0x00000300, POWERPC_EXCP_DSI); + ppc_intr_add(env, 0x00000380, POWERPC_EXCP_DSEG); + ppc_intr_add(env, 0x00000400, POWERPC_EXCP_ISI); + ppc_intr_add(env, 0x00000480, POWERPC_EXCP_ISEG); + ppc_intr_add(env, 0x00000500, POWERPC_EXCP_EXTERNAL); + ppc_intr_add(env, 0x00000600, POWERPC_EXCP_ALIGN); + ppc_intr_add(env, 0x00000700, POWERPC_EXCP_PROGRAM); + ppc_intr_add(env, 0x00000800, POWERPC_EXCP_FPU); + ppc_intr_add(env, 0x00000900, POWERPC_EXCP_DECR); + ppc_intr_add(env, 0x00000980, POWERPC_EXCP_HDECR); + ppc_intr_add(env, 0x00000C00, POWERPC_EXCP_SYSCALL); + ppc_intr_add(env, 0x00000D00, POWERPC_EXCP_TRACE); + ppc_intr_add(env, 0x00000E00, POWERPC_EXCP_HDSI); + ppc_intr_add(env, 0x00000E20, POWERPC_EXCP_HISI); + ppc_intr_add(env, 0x00000E40, POWERPC_EXCP_HV_EMU); + ppc_intr_add(env, 0x00000E60, POWERPC_EXCP_HV_MAINT); + ppc_intr_add(env, 0x00000F00, POWERPC_EXCP_PERFM); + ppc_intr_add(env, 0x00000F20, POWERPC_EXCP_VPU); + ppc_intr_add(env, 0x00000F40, POWERPC_EXCP_VSXU); /* Hardware reset vector */ env->hreset_vector = 0x0000000000000100ULL; #endif @@ -2612,10 +2613,10 @@ static void init_excp_POWER8(CPUPPCState *env) init_excp_POWER7(env); #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_SDOOR] = 0x00000A00; - env->excp_vectors[POWERPC_EXCP_FU] = 0x00000F60; - env->excp_vectors[POWERPC_EXCP_HV_FU] = 0x00000F80; - env->excp_vectors[POWERPC_EXCP_SDOOR_HV] = 0x00000E80; + ppc_intr_add(env, 0x00000A00, POWERPC_EXCP_SDOOR); + ppc_intr_add(env, 0x00000F60, POWERPC_EXCP_FU); + ppc_intr_add(env, 0x00000F80, POWERPC_EXCP_HV_FU); + ppc_intr_add(env, 0x00000E80, POWERPC_EXCP_SDOOR_HV); #endif } @@ -2624,8 +2625,8 @@ static void init_excp_POWER9(CPUPPCState *env) init_excp_POWER8(env); #if !defined(CONFIG_USER_ONLY) - env->excp_vectors[POWERPC_EXCP_HVIRT] = 0x00000EA0; - env->excp_vectors[POWERPC_EXCP_SYSCALL_VECTORED] = 0x00017000; + ppc_intr_add(env, 0x00000EA0, POWERPC_EXCP_HVIRT); + ppc_intr_add(env, 0x00017000, POWERPC_EXCP_SYSCALL_VECTORED); #endif } @@ -8375,13 +8376,8 @@ static void init_ppc_proc(PowerPCCPU *cpu) PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); CPUPPCState *env = &cpu->env; #if !defined(CONFIG_USER_ONLY) - int i; env->irq_inputs = NULL; - /* Set all exception vectors to an invalid address */ - for (i = 0; i < POWERPC_EXCP_NB; i++) { - env->excp_vectors[i] = (target_ulong)(-1ULL); - } env->ivor_mask = 0x00000000; env->ivpr_mask = 0x00000000; /* Default MMU definitions */ diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 12bf829c8f..26cbfab923 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -29,14 +29,6 @@ #endif /* #define DEBUG_OP */ -/* #define DEBUG_SOFTWARE_TLB */ -/* #define DEBUG_EXCEPTIONS */ - -#ifdef DEBUG_EXCEPTIONS -# define LOG_EXCP(...) qemu_log(__VA_ARGS__) -#else -# define LOG_EXCP(...) do { } while (0) -#endif /*****************************************************************************/ /* Exception processing */ @@ -58,32 +50,6 @@ static void ppc_hw_interrupt(CPUPPCState *env) env->error_code = 0; } #else /* defined(CONFIG_USER_ONLY) */ -static inline void dump_syscall(CPUPPCState *env) -{ - qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 - " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 - " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64 - " nip=" TARGET_FMT_lx "\n", - ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), - ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5), - ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7), - ppc_dump_gpr(env, 8), env->nip); -} - -static inline void dump_hcall(CPUPPCState *env) -{ - qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64 - " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 - " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64 - " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64 - " nip=" TARGET_FMT_lx "\n", - ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4), - ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), - ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8), - ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10), - ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12), - env->nip); -} static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, target_ulong *msr) @@ -311,17 +277,6 @@ static inline void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong new_nip, check_tlb_flush(env, false); } -struct ppc_intr_args { - target_ulong nip; - target_ulong msr; - target_ulong new_nip; - target_ulong new_msr; - int sprn_srr0; - int sprn_srr1; - int sprn_asrr0; - int sprn_asrr1; -}; - /* * Note that this function should be greatly optimized when called * with a constant excp, from ppc_hw_interrupt @@ -331,11 +286,21 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; struct ppc_intr_args regs; - int lev = -1; + PPCInterrupt *intr; + bool ignore = false; qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx " => %08x (%02x)\n", env->nip, excp, env->error_code); + if (excp == POWERPC_EXCP_NONE) { + return; + } + + if (excp < POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) { + cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); + return; + } + /* new srr1 value excluding must-be-zero bits */ if (excp_model == POWERPC_EXCP_BOOKE) { regs.msr = env->msr; @@ -380,469 +345,21 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) excp = POWERPC_EXCP_PROGRAM; } - switch (excp) { - case POWERPC_EXCP_NONE: - /* Should never happen */ - return; - case POWERPC_EXCP_CRITICAL: /* Critical input */ - switch (excp_model) { - case POWERPC_EXCP_40x: - regs.sprn_srr0 = SPR_40x_SRR2; - regs.sprn_srr1 = SPR_40x_SRR3; - break; - case POWERPC_EXCP_BOOKE: - regs.sprn_srr0 = SPR_BOOKE_CSRR0; - regs.sprn_srr1 = SPR_BOOKE_CSRR1; - break; - case POWERPC_EXCP_G2: - break; - default: - goto excp_invalid; - } - break; - case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (msr_me == 0) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } - if (env->msr_mask & MSR_HVB) { - /* - * ISA specifies HV, but can be delivered to guest with HV - * clear (e.g., see FWNMI in PAPR). - */ - regs.new_msr |= (target_ulong)MSR_HVB; - } - - /* machine check exceptions don't have ME set */ - regs.new_msr &= ~((target_ulong)1 << MSR_ME); - - /* XXX: should also have something loaded in DAR / DSISR */ - switch (excp_model) { - case POWERPC_EXCP_40x: - regs.sprn_srr0 = SPR_40x_SRR2; - regs.sprn_srr1 = SPR_40x_SRR3; - break; - case POWERPC_EXCP_BOOKE: - /* FIXME: choose one or the other based on CPU type */ - regs.sprn_srr0 = SPR_BOOKE_MCSRR0; - regs.sprn_srr1 = SPR_BOOKE_MCSRR1; - regs.sprn_asrr0 = SPR_BOOKE_CSRR0; - regs.sprn_asrr1 = SPR_BOOKE_CSRR1; - break; - default: - break; - } - break; - case POWERPC_EXCP_DSI: /* Data storage exception */ - LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx - "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]); - break; - case POWERPC_EXCP_ISI: /* Instruction storage exception */ - LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx - "\n", regs.msr, regs.nip); - regs.msr |= env->error_code; - break; - case POWERPC_EXCP_EXTERNAL: /* External input */ - { - bool lpes0; - - cs = CPU(cpu); - - /* - * Exception targeting modifiers - * - * LPES0 is supported on POWER7/8/9 - * LPES1 is not supported (old iSeries mode) - * - * On anything else, we behave as if LPES0 is 1 - * (externals don't alter MSR:HV) - */ -#if defined(TARGET_PPC64) - if (excp_model == POWERPC_EXCP_POWER7 || - excp_model == POWERPC_EXCP_POWER8 || - excp_model == POWERPC_EXCP_POWER9 || - excp_model == POWERPC_EXCP_POWER10) { - lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); - } else -#endif /* defined(TARGET_PPC64) */ - { - lpes0 = true; - } - - if (!lpes0) { - regs.new_msr |= (target_ulong)MSR_HVB; - regs.new_msr |= env->msr & ((target_ulong)1 << MSR_RI); - regs.sprn_srr0 = SPR_HSRR0; - regs.sprn_srr1 = SPR_HSRR1; - } - if (env->mpic_proxy) { - /* IACK the IRQ on delivery */ - env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); - } - break; + intr = &env->entry_points[excp]; + if (!intr->setup_regs) { + cpu_abort(cs, "Raised an exception without defined vector %d\n", + excp); } - case POWERPC_EXCP_ALIGN: /* Alignment exception */ - /* Get rS/rD and rA from faulting opcode */ - /* - * Note: the opcode fields will not be set properly for a - * direct store load/store, but nobody cares as nobody - * actually uses direct store segments. - */ - env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; - break; - case POWERPC_EXCP_PROGRAM: /* Program exception */ - switch (env->error_code & ~0xF) { - case POWERPC_EXCP_FP: - if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) { - LOG_EXCP("Ignore floating point exception\n"); - cs->exception_index = POWERPC_EXCP_NONE; - env->error_code = 0; - return; - } - /* - * FP exceptions always have NIP pointing to the faulting - * instruction, so always use store_next and claim we are - * precise in the MSR. - */ - regs.msr |= 0x00100000; - env->spr[SPR_BOOKE_ESR] = ESR_FP; - break; - case POWERPC_EXCP_INVAL: - LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", regs.nip); - regs.msr |= 0x00080000; - env->spr[SPR_BOOKE_ESR] = ESR_PIL; - break; - case POWERPC_EXCP_PRIV: - regs.msr |= 0x00040000; - env->spr[SPR_BOOKE_ESR] = ESR_PPR; - break; - case POWERPC_EXCP_TRAP: - regs.msr |= 0x00020000; - env->spr[SPR_BOOKE_ESR] = ESR_PTR; - break; - default: - /* Should never occur */ - cpu_abort(cs, "Invalid program exception %d. Aborting\n", - env->error_code); - break; - } - break; - case POWERPC_EXCP_SYSCALL: /* System call exception */ - lev = env->error_code; - - if ((lev == 1) && cpu->vhyp) { - dump_hcall(env); - } else { - dump_syscall(env); - } + regs.new_nip = intr->addr | env->excp_prefix; + intr->setup_regs(cpu, intr, excp_model, ®s, &ignore); + if (ignore) { /* - * We need to correct the NIP which in this case is supposed - * to point to the next instruction. We also set env->nip here - * because the modification needs to be accessible by the - * virtual hypervisor code below. + * The interrupt was ignored or delivered by other means + * (e.g. vhyp). */ - regs.nip += 4; - env->nip = regs.nip; - - /* "PAPR mode" built-in hypercall emulation */ - if ((lev == 1) && cpu->vhyp) { - PPCVirtualHypervisorClass *vhc = - PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); - vhc->hypercall(cpu->vhyp, cpu); - return; - } - - if (lev == 1) { - regs.new_msr |= (target_ulong)MSR_HVB; - } - break; - case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */ - lev = env->error_code; - dump_syscall(env); - regs.nip += 4; - regs.new_msr |= env->msr & ((target_ulong)1 << MSR_EE); - regs.new_msr |= env->msr & ((target_ulong)1 << MSR_RI); - break; - case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ - case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ - case POWERPC_EXCP_DECR: /* Decrementer exception */ - break; - case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ - /* FIT on 4xx */ - LOG_EXCP("FIT exception\n"); - break; - case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ - LOG_EXCP("WDT exception\n"); - switch (excp_model) { - case POWERPC_EXCP_BOOKE: - regs.sprn_srr0 = SPR_BOOKE_CSRR0; - regs.sprn_srr1 = SPR_BOOKE_CSRR1; - break; - default: - break; - } - break; - case POWERPC_EXCP_DTLB: /* Data TLB error */ - case POWERPC_EXCP_ITLB: /* Instruction TLB error */ - break; - case POWERPC_EXCP_DEBUG: /* Debug interrupt */ - if (env->flags & POWERPC_FLAG_DE) { - /* FIXME: choose one or the other based on CPU type */ - regs.sprn_srr0 = SPR_BOOKE_DSRR0; - regs.sprn_srr1 = SPR_BOOKE_DSRR1; - regs.sprn_asrr0 = SPR_BOOKE_CSRR0; - regs.sprn_asrr1 = SPR_BOOKE_CSRR1; - /* DBSR already modified by caller */ - } else { - cpu_abort(cs, "Debug exception triggered on unsupported model\n"); - } - break; - case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */ - env->spr[SPR_BOOKE_ESR] = ESR_SPV; - break; - case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ - /* XXX: TODO */ - cpu_abort(cs, "Embedded floating point data exception " - "is not implemented yet !\n"); - env->spr[SPR_BOOKE_ESR] = ESR_SPV; - break; - case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ - /* XXX: TODO */ - cpu_abort(cs, "Embedded floating point round exception " - "is not implemented yet !\n"); - env->spr[SPR_BOOKE_ESR] = ESR_SPV; - break; - case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ - /* XXX: TODO */ - cpu_abort(cs, - "Performance counter exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ - break; - case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ - regs.sprn_srr0 = SPR_BOOKE_CSRR0; - regs.sprn_srr1 = SPR_BOOKE_CSRR1; - break; - case POWERPC_EXCP_RESET: /* System reset exception */ - /* A power-saving exception sets ME, otherwise it is unchanged */ - if (msr_pow) { - /* indicate that we resumed from power save mode */ - regs.msr |= 0x10000; - regs.new_msr |= ((target_ulong)1 << MSR_ME); - } - if (env->msr_mask & MSR_HVB) { - /* - * ISA specifies HV, but can be delivered to guest with HV - * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU). - */ - regs.new_msr |= (target_ulong)MSR_HVB; - } else { - if (msr_pow) { - cpu_abort(cs, "Trying to deliver power-saving system reset " - "exception %d with no HV support\n", excp); - } - } - break; - case POWERPC_EXCP_DSEG: /* Data segment exception */ - case POWERPC_EXCP_ISEG: /* Instruction segment exception */ - case POWERPC_EXCP_TRACE: /* Trace exception */ - break; - case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ - regs.msr |= env->error_code; - /* fall through */ - case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ - case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ - case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ - case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ - case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ - case POWERPC_EXCP_HV_EMU: - case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ - regs.sprn_srr0 = SPR_HSRR0; - regs.sprn_srr1 = SPR_HSRR1; - regs.new_msr |= (target_ulong)MSR_HVB; - regs.new_msr |= env->msr & ((target_ulong)1 << MSR_RI); - break; - case POWERPC_EXCP_VPU: /* Vector unavailable exception */ - case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ - case POWERPC_EXCP_FU: /* Facility unavailable exception */ -#ifdef TARGET_PPC64 - env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56); -#endif - break; - case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */ -#ifdef TARGET_PPC64 - env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); - regs.sprn_srr0 = SPR_HSRR0; - regs.sprn_srr1 = SPR_HSRR1; - regs.new_msr |= (target_ulong)MSR_HVB; - regs.new_msr |= env->msr & ((target_ulong)1 << MSR_RI); -#endif - break; - case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ - LOG_EXCP("PIT exception\n"); - break; - case POWERPC_EXCP_IO: /* IO error exception */ - /* XXX: TODO */ - cpu_abort(cs, "601 IO error exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_RUNM: /* Run mode exception */ - /* XXX: TODO */ - cpu_abort(cs, "601 run mode exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_EMUL: /* Emulation trap exception */ - /* XXX: TODO */ - cpu_abort(cs, "602 emulation trap exception " - "is not implemented yet !\n"); - break; - case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ - case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ - case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ - switch (excp_model) { - case POWERPC_EXCP_602: - case POWERPC_EXCP_603: - case POWERPC_EXCP_603E: - case POWERPC_EXCP_G2: - /* Swap temporary saved registers with GPRs */ - if (!(regs.new_msr & ((target_ulong)1 << MSR_TGPR))) { - regs.new_msr |= (target_ulong)1 << MSR_TGPR; - hreg_swap_gpr_tgpr(env); - } - /* fall through */ - case POWERPC_EXCP_7x5: -#if defined(DEBUG_SOFTWARE_TLB) - if (qemu_log_enabled()) { - const char *es; - target_ulong *miss, *cmp; - int en; - - if (excp == POWERPC_EXCP_IFTLB) { - es = "I"; - en = 'I'; - miss = &env->spr[SPR_IMISS]; - cmp = &env->spr[SPR_ICMP]; - } else { - if (excp == POWERPC_EXCP_DLTLB) { - es = "DL"; - } else { - es = "DS"; - } - en = 'D'; - miss = &env->spr[SPR_DMISS]; - cmp = &env->spr[SPR_DCMP]; - } - qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " - TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 " - TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, - env->spr[SPR_HASH1], env->spr[SPR_HASH2], - env->error_code); - } -#endif - regs.msr |= env->crf[0] << 28; - regs.msr |= env->error_code; /* key, D/I, S/L bits */ - /* Set way using a LRU mechanism */ - regs.msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; - break; - case POWERPC_EXCP_74xx: -#if defined(DEBUG_SOFTWARE_TLB) - if (qemu_log_enabled()) { - const char *es; - target_ulong *miss, *cmp; - int en; - - if (excp == POWERPC_EXCP_IFTLB) { - es = "I"; - en = 'I'; - miss = &env->spr[SPR_TLBMISS]; - cmp = &env->spr[SPR_PTEHI]; - } else { - if (excp == POWERPC_EXCP_DLTLB) { - es = "DL"; - } else { - es = "DS"; - } - en = 'D'; - miss = &env->spr[SPR_TLBMISS]; - cmp = &env->spr[SPR_PTEHI]; - } - qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " - TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, - env->error_code); - } -#endif - regs.msr |= env->error_code; /* key bit */ - break; - default: - cpu_abort(cs, "Invalid TLB miss exception\n"); - break; - } - break; - case POWERPC_EXCP_FPA: /* Floating-point assist exception */ - /* XXX: TODO */ - cpu_abort(cs, "Floating point assist exception " - "is not implemented yet !\n"); - break; - case POWERPC_EXCP_DABR: /* Data address breakpoint */ - /* XXX: TODO */ - cpu_abort(cs, "DABR exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ - /* XXX: TODO */ - cpu_abort(cs, "IABR exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_SMI: /* System management interrupt */ - /* XXX: TODO */ - cpu_abort(cs, "SMI exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_THERM: /* Thermal interrupt */ - /* XXX: TODO */ - cpu_abort(cs, "Thermal management exception " - "is not implemented yet !\n"); - break; - case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ - /* XXX: TODO */ - cpu_abort(cs, - "Performance counter exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_VPUA: /* Vector assist exception */ - /* XXX: TODO */ - cpu_abort(cs, "VPU assist exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_SOFTP: /* Soft patch exception */ - /* XXX: TODO */ - cpu_abort(cs, - "970 soft-patch exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_MAINT: /* Maintenance exception */ - /* XXX: TODO */ - cpu_abort(cs, - "970 maintenance exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ - /* XXX: TODO */ - cpu_abort(cs, "Maskable external exception " - "is not implemented yet !\n"); - break; - case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ - /* XXX: TODO */ - cpu_abort(cs, "Non maskable external exception " - "is not implemented yet !\n"); - break; - default: - excp_invalid: - cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); - break; + return; } /* Sanity check */ @@ -892,14 +409,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } #endif - regs.new_nip = env->excp_vectors[excp]; - if (regs.new_nip == (target_ulong)-1ULL) { - cpu_abort(cs, "Raised an exception without defined vector %d\n", - excp); - } - - regs.new_nip |= env->excp_prefix; - /* If any alternate SRR register are defined, duplicate saved values */ if (regs.sprn_asrr0 != -1) { env->spr[regs.sprn_asrr0] = regs.nip; @@ -925,24 +434,16 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } #endif - if (excp != POWERPC_EXCP_SYSCALL_VECTORED) { + if (intr->id != POWERPC_EXCP_SYSCALL_VECTORED) { /* Save PC */ env->spr[regs.sprn_srr0] = regs.nip; /* Save MSR */ env->spr[regs.sprn_srr1] = regs.msr; - -#if defined(TARGET_PPC64) - } else { - regs.new_nip += lev * 0x20; - - env->lr = regs.nip; - env->ctr = regs.msr; -#endif } /* This can update regs.new_msr and regs.new_nip if AIL applies */ - ppc_excp_apply_ail(cpu, excp_model, excp, regs.msr, ®s.new_msr, + ppc_excp_apply_ail(cpu, excp_model, intr->id, regs.msr, ®s.new_msr, ®s.new_nip); powerpc_set_excp_state(cpu, regs.new_nip, regs.new_msr); diff --git a/target/ppc/interrupts.c b/target/ppc/interrupts.c new file mode 100644 index 0000000000..31faea84c5 --- /dev/null +++ b/target/ppc/interrupts.c @@ -0,0 +1,638 @@ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "cpu.h" +#include "ppc_intr.h" + +/* for hreg_swap_gpr_tgpr */ +#include "helper_regs.h" + +/* #define DEBUG_SOFTWARE_TLB */ +/* #define DEBUG_EXCEPTIONS */ + +#ifdef DEBUG_EXCEPTIONS +# define LOG_EXCP(...) qemu_log(__VA_ARGS__) +#else +# define LOG_EXCP(...) do { } while (0) +#endif + +void __ppc_intr_add(CPUPPCState *env, target_ulong addr, int id, + const char *intr_name) +{ + PPCInterrupt *intr = &env->entry_points[id]; + + object_initialize(intr, sizeof(*intr), intr_name); + intr->addr = addr; +} + +static const TypeInfo ppc_interrupt_info = { + .name = TYPE_PPC_INTERRUPT, + .parent = TYPE_OBJECT, + .abstract = true, +}; + +static void ppc_interrupt_register_types(void) +{ + type_register_static(&ppc_interrupt_info); +} +type_init(ppc_interrupt_register_types); + + + +static void ppc_intr_def_log(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, bool *ignore) +{ + LOG_EXCP("%s interrupt\n", intr->name); +} + +static void ppc_intr_def_not_impl(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + CPUState *cs = CPU(cpu); + + cpu_abort(cs, "%s interrupt not implemented yet.\n", intr->name); +} + +static void ppc_intr_def_no_op(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ +} + +/* Default implementation for interrupts that set the MSR_HV bit */ +static void ppc_intr_def_hv(PowerPCCPU *cpu, PPCInterrupt *intr, int excp_model, + ppc_intr_args *regs, bool *ignore) +{ + CPUPPCState *env = &cpu->env; + + regs->sprn_srr0 = SPR_HSRR0; + regs->sprn_srr1 = SPR_HSRR1; + regs->new_msr |= (target_ulong)MSR_HVB; + regs->new_msr |= env->msr & ((target_ulong)1 << MSR_RI); +} + +/* Default implementation for Facility Unavailable interrupts */ +static void ppc_intr_def_fac_unavail_64(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ +#ifdef TARGET_PPC64 + CPUPPCState *env = &cpu->env; + env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); +#endif +} + +static void ppc_debug_software_tlb(CPUPPCState *env, int excp, int excp_model, + int imiss_sprn, int icmp_sprn, + int dmiss_sprn, int dcmp_sprn) +{ +#if defined(DEBUG_SOFTWARE_TLB) + if (qemu_log_enabled()) { + const char *es; + target_ulong *miss, *cmp; + int en; + + if (excp == POWERPC_EXCP_IFTLB) { + es = "I"; + en = 'I'; + miss = &env->spr[imiss_sprn]; + cmp = &env->spr[icmp_sprn]; + } else { + if (excp == POWERPC_EXCP_DLTLB) { + es = "DL"; + } else { + es = "DS"; + } + en = 'D'; + miss = &env->spr[dmiss_sprn]; + cmp = &env->spr[dcmp_srpn]; + } + + if (excp_model == POWERPC_EXCP_74xx) { + qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " + TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, + env->error_code); + } else { + qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " + TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 " + TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, + env->spr[SPR_HASH1], env->spr[SPR_HASH2], + env->error_code); + } + } +#endif +} + +static void ppc_intr_def_tlb_miss(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + + switch (excp_model) { + case POWERPC_EXCP_602: + case POWERPC_EXCP_603: + case POWERPC_EXCP_603E: + case POWERPC_EXCP_G2: + /* Swap temporary saved registers with GPRs */ + if (!(regs->new_msr & ((target_ulong)1 << MSR_TGPR))) { + regs->new_msr |= (target_ulong)1 << MSR_TGPR; + hreg_swap_gpr_tgpr(env); + } + + ppc_debug_software_tlb(env, intr->id, excp_model, + SPR_IMISS, SPR_ICMP, + SPR_DMISS, SPR_DCMP); + + /* fall through */ + case POWERPC_EXCP_7x5: + regs->msr |= env->crf[0] << 28; + regs->msr |= env->error_code; /* key, D/I, S/L bits */ + + /* Set way using a LRU mechanism */ + regs->msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; + + break; + case POWERPC_EXCP_74xx: + ppc_debug_software_tlb(env, intr->id, excp_model, + SPR_TLBMISS, SPR_PTEHI, + SPR_TLBMISS, SPR_PTEHI); + + regs->msr |= env->error_code; /* key bit */ + break; + default: + cpu_abort(cs, "Invalid instruction TLB miss exception\n"); + break; + } +} + +static void ppc_intr_critical(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, bool *ignore) +{ + CPUState *cs = CPU(cpu); + + switch (excp_model) { + case POWERPC_EXCP_40x: + regs->sprn_srr0 = SPR_40x_SRR2; + regs->sprn_srr1 = SPR_40x_SRR3; + break; + case POWERPC_EXCP_BOOKE: + regs->sprn_srr0 = SPR_BOOKE_CSRR0; + regs->sprn_srr1 = SPR_BOOKE_CSRR1; + break; + case POWERPC_EXCP_G2: + break; + default: + cpu_abort(cs, "Invalid Critical interrupt for model %d. Aborting\n", + excp_model); + break; + } +} +PPC_DEFINE_INTR(POWERPC_EXCP_CRITICAL, critical, "Critical input"); + +static void ppc_intr_machine_check(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + + if (msr_me == 0) { + /* + * Machine check exception is not enabled. Enter + * checkstop state. + */ + fprintf(stderr, "Machine check while not allowed. " + "Entering checkstop state\n"); + if (qemu_log_separate()) { + qemu_log("Machine check while not allowed. " + "Entering checkstop state\n"); + } + cs->halted = 1; + cpu_interrupt_exittb(cs); + } + if (env->msr_mask & MSR_HVB) { + /* + * ISA specifies HV, but can be delivered to guest with HV + * clear (e.g., see FWNMI in PAPR). + */ + regs->new_msr |= (target_ulong)MSR_HVB; + } + + /* machine check exceptions don't have ME set */ + regs->new_msr &= ~((target_ulong)1 << MSR_ME); + + /* XXX: should also have something loaded in DAR / DSISR */ + switch (excp_model) { + case POWERPC_EXCP_40x: + regs->sprn_srr0 = SPR_40x_SRR2; + regs->sprn_srr1 = SPR_40x_SRR3; + break; + case POWERPC_EXCP_BOOKE: + /* FIXME: choose one or the other based on CPU type */ + regs->sprn_srr0 = SPR_BOOKE_MCSRR0; + regs->sprn_srr1 = SPR_BOOKE_MCSRR1; + regs->sprn_asrr0 = SPR_BOOKE_CSRR0; + regs->sprn_asrr1 = SPR_BOOKE_CSRR1; + break; + default: + break; + } +} +PPC_DEFINE_INTR(POWERPC_EXCP_MCHECK, machine_check, "Machine check"); + +static void ppc_intr_data_storage(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx + "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]); +} +PPC_DEFINE_INTR(POWERPC_EXCP_DSI, data_storage, "Data storage"); + +static void ppc_intr_insn_storage(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + CPUPPCState *env = &cpu->env; + + LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx + "\n", regs->msr, regs->nip); + regs->msr |= env->error_code; +} +PPC_DEFINE_INTR(POWERPC_EXCP_ISI, insn_storage, "Instruction storage"); + +static void ppc_intr_external(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, bool *ignore) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + bool lpes0; + + /* + * Exception targeting modifiers + * + * LPES0 is supported on POWER7/8/9 + * LPES1 is not supported (old iSeries mode) + * + * On anything else, we behave as if LPES0 is 1 + * (externals don't alter MSR:HV) + */ +#if defined(TARGET_PPC64) + if (excp_model == POWERPC_EXCP_POWER7 || + excp_model == POWERPC_EXCP_POWER8 || + excp_model == POWERPC_EXCP_POWER9 || + excp_model == POWERPC_EXCP_POWER10) { + lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); + } else +#endif /* defined(TARGET_PPC64) */ + { + lpes0 = true; + } + + if (!lpes0) { + regs->new_msr |= (target_ulong)MSR_HVB; + regs->new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + regs->sprn_srr0 = SPR_HSRR0; + regs->sprn_srr1 = SPR_HSRR1; + } + if (env->mpic_proxy) { + /* IACK the IRQ on delivery */ + env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); + } +} +PPC_DEFINE_INTR(POWERPC_EXCP_EXTERNAL, external, "External"); + +static void ppc_intr_alignment(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + CPUPPCState *env = &cpu->env; + + /* Get rS/rD and rA from faulting opcode */ + /* + * Note: the opcode fields will not be set properly for a + * direct store load/store, but nobody cares as nobody + * actually uses direct store segments. + */ + env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; +} +PPC_DEFINE_INTR(POWERPC_EXCP_ALIGN, alignment, "Alignment"); + +static void ppc_intr_program(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, bool *ignore) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + + switch (env->error_code & ~0xF) { + case POWERPC_EXCP_FP: + if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) { + LOG_EXCP("Ignore floating point exception\n"); + cs->exception_index = POWERPC_EXCP_NONE; + env->error_code = 0; + + *ignore = true; + return; + } + + /* + * FP exceptions always have NIP pointing to the faulting + * instruction, so always use store_next and claim we are + * precise in the MSR. + */ + regs->msr |= 0x00100000; + env->spr[SPR_BOOKE_ESR] = ESR_FP; + break; + case POWERPC_EXCP_INVAL: + LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", regs->nip); + regs->msr |= 0x00080000; + env->spr[SPR_BOOKE_ESR] = ESR_PIL; + break; + case POWERPC_EXCP_PRIV: + regs->msr |= 0x00040000; + env->spr[SPR_BOOKE_ESR] = ESR_PPR; + break; + case POWERPC_EXCP_TRAP: + regs->msr |= 0x00020000; + env->spr[SPR_BOOKE_ESR] = ESR_PTR; + break; + default: + /* Should never occur */ + cpu_abort(cs, "Invalid program exception %d. Aborting\n", + env->error_code); + break; + } +} +PPC_DEFINE_INTR(POWERPC_EXCP_PROGRAM, program, "Program"); + + +static inline void dump_syscall(CPUPPCState *env) +{ + qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 + " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 + " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64 + " nip=" TARGET_FMT_lx "\n", + ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), + ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5), + ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7), + ppc_dump_gpr(env, 8), env->nip); +} + +static inline void dump_hcall(CPUPPCState *env) +{ + qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64 + " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 + " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64 + " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64 + " nip=" TARGET_FMT_lx "\n", + ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4), + ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), + ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8), + ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10), + ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12), + env->nip); +} + + +static void ppc_intr_system_call(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + CPUPPCState *env = &cpu->env; + int lev; + + lev = env->error_code; + + if ((lev == 1) && cpu->vhyp) { + dump_hcall(env); + } else { + dump_syscall(env); + } + + /* + * We need to correct the NIP which in this case is supposed + * to point to the next instruction. We also set env->nip here + * because the modification needs to be accessible by the + * virtual hypervisor code below. + */ + regs->nip += 4; + env->nip = regs->nip; + + /* "PAPR mode" built-in hypercall emulation */ + if ((lev == 1) && cpu->vhyp) { + PPCVirtualHypervisorClass *vhc = + PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); + vhc->hypercall(cpu->vhyp, cpu); + + *ignore = true; + return; + } + + if (lev == 1) { + regs->new_msr |= (target_ulong)MSR_HVB; + } +} +PPC_DEFINE_INTR(POWERPC_EXCP_SYSCALL, system_call, "System call"); + +static void ppc_intr_system_call_vectored(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + CPUPPCState *env = &cpu->env; + int lev; + + lev = env->error_code; + dump_syscall(env); + + regs->nip += 4; + regs->new_msr |= env->msr & ((target_ulong)1 << MSR_EE); + regs->new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + regs->new_nip += lev * 0x20; + + env->lr = regs->nip; + env->ctr = regs->msr; +} +PPC_DEFINE_INTR(POWERPC_EXCP_SYSCALL_VECTORED, system_call_vectored, + "System call vectored"); + +static void ppc_intr_watchdog(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, bool *ignore) +{ + LOG_EXCP("WDT exception\n"); + switch (excp_model) { + case POWERPC_EXCP_BOOKE: + regs->sprn_srr0 = SPR_BOOKE_CSRR0; + regs->sprn_srr1 = SPR_BOOKE_CSRR1; + break; + default: + break; + } +} +PPC_DEFINE_INTR(POWERPC_EXCP_WDT, watchdog, "Watchdog timer"); + +static void ppc_intr_debug(PowerPCCPU *cpu, PPCInterrupt *intr, int excp_model, + ppc_intr_args *regs, bool *ignore) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + + if (env->flags & POWERPC_FLAG_DE) { + /* FIXME: choose one or the other based on CPU type */ + regs->sprn_srr0 = SPR_BOOKE_DSRR0; + regs->sprn_srr1 = SPR_BOOKE_DSRR1; + regs->sprn_asrr0 = SPR_BOOKE_CSRR0; + regs->sprn_asrr1 = SPR_BOOKE_CSRR1; + /* DBSR already modified by caller */ + } else { + cpu_abort(cs, "Debug exception triggered on unsupported model\n"); + } +} +PPC_DEFINE_INTR(POWERPC_EXCP_DEBUG, debug, "Debug"); + +static void ppc_intr_spe_unavailable(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + CPUPPCState *env = &cpu->env; + + env->spr[SPR_BOOKE_ESR] = ESR_SPV; +} +PPC_DEFINE_INTR(POWERPC_EXCP_SPEU, spe_unavailable, + "SPE/embedded floating-point unavailable"); + +static void ppc_intr_embedded_fp_data(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + CPUPPCState *env = &cpu->env; + + ppc_intr_def_not_impl(cpu, intr, excp_model, regs, ignore); + env->spr[SPR_BOOKE_ESR] = ESR_SPV; +} +PPC_DEFINE_INTR(POWERPC_EXCP_EFPDI, embedded_fp_data, + "Embedded floating-point data"); + +static void ppc_intr_embedded_fp_round(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + CPUPPCState *env = &cpu->env; + + ppc_intr_def_not_impl(cpu, intr, excp_model, regs, ignore); + env->spr[SPR_BOOKE_ESR] = ESR_SPV; +} +PPC_DEFINE_INTR(POWERPC_EXCP_EFPRI, embedded_fp_round, + "Embedded floating-point round"); + +static void ppc_intr_embedded_doorbell_crit(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + regs->sprn_srr0 = SPR_BOOKE_CSRR0; + regs->sprn_srr1 = SPR_BOOKE_CSRR1; +} +PPC_DEFINE_INTR(POWERPC_EXCP_DOORCI, embedded_doorbell_crit, + "Embedded doorbell critical"); + +static void ppc_intr_system_reset(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + + /* A power-saving exception sets ME, otherwise it is unchanged */ + if (msr_pow) { + /* indicate that we resumed from power save mode */ + regs->msr |= 0x10000; + regs->new_msr |= ((target_ulong)1 << MSR_ME); + } + if (env->msr_mask & MSR_HVB) { + /* + * ISA specifies HV, but can be delivered to guest with HV + * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU). + */ + regs->new_msr |= (target_ulong)MSR_HVB; + } else { + if (msr_pow) { + cpu_abort(cs, "Trying to deliver power-saving system reset " + "exception with no HV support\n"); + } + } +} +PPC_DEFINE_INTR(POWERPC_EXCP_RESET, system_reset, "System reset"); + +static void ppc_intr_hv_insn_storage(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ + CPUPPCState *env = &cpu->env; + + regs->msr |= env->error_code; + ppc_intr_def_hv(cpu, intr, excp_model, regs, ignore); +} +PPC_DEFINE_INTR(POWERPC_EXCP_HISI, hv_insn_storage, + "Hypervisor instruction storage"); + +static void ppc_intr_hv_facility_unavail(PowerPCCPU *cpu, PPCInterrupt *intr, + int excp_model, ppc_intr_args *regs, + bool *ignore) +{ +#ifdef TARGET_PPC64 + ppc_intr_def_fac_unavail_64(cpu, intr, excp_model, regs, ignore); + ppc_intr_def_hv(cpu, intr, excp_model, regs, ignore); +#endif +} +PPC_DEFINE_INTR(POWERPC_EXCP_HV_FU, hv_facility_unavail, + "Hypervisor facility unavailable"); + +PPC_DEFINE_INTR(POWERPC_EXCP_HDECR, def_hv, "Hypervisor decrementer"); +PPC_DEFINE_INTR(POWERPC_EXCP_HDSI, def_hv, "Hypervisor data storage"); +PPC_DEFINE_INTR(POWERPC_EXCP_HDSEG, def_hv, "Hypervisor data segment"); +PPC_DEFINE_INTR(POWERPC_EXCP_HISEG, def_hv, "Hypervisor insn segment"); +PPC_DEFINE_INTR(POWERPC_EXCP_SDOOR_HV, def_hv, "Hypervisor doorbell"); +PPC_DEFINE_INTR(POWERPC_EXCP_HV_EMU, def_hv, "Hypervisor emulation assist"); +PPC_DEFINE_INTR(POWERPC_EXCP_HVIRT, def_hv, "Hypervisor virtualization"); + +PPC_DEFINE_INTR(POWERPC_EXCP_VPU, def_fac_unavail_64, "Vector unavailable"); +PPC_DEFINE_INTR(POWERPC_EXCP_VSXU, def_fac_unavail_64, "VSX unavailable"); +PPC_DEFINE_INTR(POWERPC_EXCP_FU, def_fac_unavail_64, "Facility unavailable"); + +PPC_DEFINE_INTR(POWERPC_EXCP_IFTLB, def_tlb_miss, "Insn fetch TLB error"); +PPC_DEFINE_INTR(POWERPC_EXCP_DLTLB, def_tlb_miss, "Data load TLB error"); +PPC_DEFINE_INTR(POWERPC_EXCP_DSTLB, def_tlb_miss, "Data store TLB error"); + +PPC_DEFINE_INTR(POWERPC_EXCP_FIT, def_log, "Fixed-interval timer"); +PPC_DEFINE_INTR(POWERPC_EXCP_PIT, def_log, "Programmable interval timer"); + +PPC_DEFINE_INTR(POWERPC_EXCP_FPU, def_no_op, "Floating-point unavailable"); +PPC_DEFINE_INTR(POWERPC_EXCP_APU, def_no_op, "Aux. processor unavailable"); +PPC_DEFINE_INTR(POWERPC_EXCP_DECR, def_no_op, "Decrementer"); +PPC_DEFINE_INTR(POWERPC_EXCP_DTLB, def_no_op, "Data TLB error"); +PPC_DEFINE_INTR(POWERPC_EXCP_ITLB, def_no_op, "Instruction TLB error"); +PPC_DEFINE_INTR(POWERPC_EXCP_DOORI, def_no_op, "Embedded doorbell"); +PPC_DEFINE_INTR(POWERPC_EXCP_DSEG, def_no_op, "Data segment"); +PPC_DEFINE_INTR(POWERPC_EXCP_ISEG, def_no_op, "Instruction segment"); +PPC_DEFINE_INTR(POWERPC_EXCP_TRACE, def_no_op, "Trace"); + +PPC_DEFINE_INTR(POWERPC_EXCP_EPERFM, def_not_impl, "Embedded perf. monitor"); +PPC_DEFINE_INTR(POWERPC_EXCP_IO, def_not_impl, "IO error"); +PPC_DEFINE_INTR(POWERPC_EXCP_RUNM, def_not_impl, "Run mode"); +PPC_DEFINE_INTR(POWERPC_EXCP_EMUL, def_not_impl, "Emulation trap"); +PPC_DEFINE_INTR(POWERPC_EXCP_FPA, def_not_impl, "Floating-point assist"); +PPC_DEFINE_INTR(POWERPC_EXCP_DABR, def_not_impl, "Data address breakpoint"); +PPC_DEFINE_INTR(POWERPC_EXCP_IABR, def_not_impl, "Insn address breakpoint"); +PPC_DEFINE_INTR(POWERPC_EXCP_SMI, def_not_impl, "System management"); +PPC_DEFINE_INTR(POWERPC_EXCP_THERM, def_not_impl, "Thermal management"); +PPC_DEFINE_INTR(POWERPC_EXCP_PERFM, def_not_impl, "Performance counter"); +PPC_DEFINE_INTR(POWERPC_EXCP_VPUA, def_not_impl, "Vector assist"); +PPC_DEFINE_INTR(POWERPC_EXCP_SOFTP, def_not_impl, "Soft patch"); +PPC_DEFINE_INTR(POWERPC_EXCP_MAINT, def_not_impl, "Maintenance"); +PPC_DEFINE_INTR(POWERPC_EXCP_MEXTBR, def_not_impl, "Maskable external"); +PPC_DEFINE_INTR(POWERPC_EXCP_NMEXTBR, def_not_impl, "Non-maskable external"); + +/* These are used by P7 and P8 but were never implemented */ +PPC_DEFINE_INTR(POWERPC_EXCP_SDOOR, def_not_impl, "Server doorbell"); +PPC_DEFINE_INTR(POWERPC_EXCP_HV_MAINT, def_not_impl, "Hypervisor maintenance"); diff --git a/target/ppc/machine.c b/target/ppc/machine.c index 93972df58e..3927359c7b 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -115,7 +115,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) qemu_get_be32s(f, &env->pending_interrupts); qemu_get_be32s(f, &env->irq_input_state); for (i = 0; i < POWERPC_EXCP_NB; i++) { - qemu_get_betls(f, &env->excp_vectors[i]); + qemu_get_betls(f, &env->entry_points[i].addr); } qemu_get_betls(f, &env->excp_prefix); qemu_get_betls(f, &env->ivor_mask); diff --git a/target/ppc/meson.build b/target/ppc/meson.build index a6a53a8d5c..740eac25f7 100644 --- a/target/ppc/meson.build +++ b/target/ppc/meson.build @@ -30,6 +30,7 @@ ppc_softmmu_ss.add(files( 'mmu-hash32.c', 'mmu_helper.c', 'monitor.c', + 'interrupts.c', )) ppc_softmmu_ss.add(when: 'CONFIG_TCG', if_false: files( 'tcg-stub.c' diff --git a/target/ppc/ppc_intr.h b/target/ppc/ppc_intr.h new file mode 100644 index 0000000000..e588736c6d --- /dev/null +++ b/target/ppc/ppc_intr.h @@ -0,0 +1,55 @@ +#ifndef PPC_INTR_H +#define PPC_INTR_H + +#include "qom/object.h" +#include "cpu-qom.h" + +#define TYPE_PPC_INTERRUPT "ppc-interrupt" +OBJECT_DECLARE_SIMPLE_TYPE(PPCInterrupt, PPC_INTERRUPT) + +void __ppc_intr_add(CPUPPCState *env, target_ulong addr, int id, + const char *intr_name); + +#define ppc_intr_add(_env, _addr, _id) \ + do { \ + QEMU_BUILD_BUG_ON(_id <= POWERPC_EXCP_NONE); \ + QEMU_BUILD_BUG_ON(_id >= POWERPC_EXCP_NB); \ + __ppc_intr_add(_env, _addr, _id, #_id); \ + } while (0) \ + +/* + * Registers an interrupt callback as a class. This makes it so that + * the interrupt callback implementation is stored on QOM and we can + * instantiate only the ones needed for a specific processor later. + * + * @_id: The interrupt id as in the POWERPC_EXCP_* enum. This will be + * the QOM hash table key for the type. + * @_sym: The interrupt name as a valid C identifier. This will be + * used to compose the symbol name for the callback to be invoked + * for this interrupt. + * @_name: The interrupt name as a string for display. + */ +#define PPC_DEFINE_INTR(_id, _sym, _name) \ + \ + static void __##_id##_init(Object *obj) \ + { \ + PPCInterrupt *pi = PPC_INTERRUPT(obj); \ + \ + pi->id = _id; \ + pi->name = _name; \ + pi->setup_regs = ppc_intr_##_sym; \ + } \ + \ + static const TypeInfo __##_id##_info = { \ + .parent = TYPE_PPC_INTERRUPT, \ + .name = #_id, \ + .instance_init = __##_id##_init, \ + }; \ + \ + static void __##_id##_register_types(void) \ + { \ + type_register_static(&__##_id##_info); \ + } \ + type_init(__##_id##_register_types); \ + +#endif /* PPC_INTR_H */ diff --git a/target/ppc/translate.c b/target/ppc/translate.c index e16a2721e2..2c82bda8cc 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -951,7 +951,8 @@ void spr_write_excp_vector(DisasContext *ctx, int sprn, int gprn) TCGv t0 = tcg_temp_new(); tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUPPCState, ivor_mask)); tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]); - tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_vectors[sprn_offs])); + tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, entry_points[sprn_offs]) + + offsetof(PPCInterrupt, addr)); gen_store_spr(sprn, t0); tcg_temp_free(t0); }