From patchwork Thu Mar 31 14:58:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Leandro Lupori X-Patchwork-Id: 1611822 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) 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 bilbo.ozlabs.org (Postfix) with ESMTPS id 4KTnGG35vYz9sGP for ; Fri, 1 Apr 2022 02:26:46 +1100 (AEDT) Received: from localhost ([::1]:60114 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nZwhA-0004Ff-9w for incoming@patchwork.ozlabs.org; Thu, 31 Mar 2022 11:26:44 -0400 Received: from eggs.gnu.org ([209.51.188.92]:56268) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nZwfa-0003d0-4S; Thu, 31 Mar 2022 11:25:06 -0400 Received: from [187.72.171.209] (port=51585 helo=outlook.eldorado.org.br) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nZwfY-0004ne-Aa; Thu, 31 Mar 2022 11:25:05 -0400 Received: from p9ibm ([10.10.71.235]) by outlook.eldorado.org.br over TLS secured channel with Microsoft SMTPSVC(8.5.9600.16384); Thu, 31 Mar 2022 12:24:02 -0300 Received: from eldorado.org.br (unknown [10.10.70.45]) by p9ibm (Postfix) with ESMTP id D875880060F; Thu, 31 Mar 2022 11:58:42 -0300 (-03) From: Leandro Lupori To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Subject: [RFC PATCH v2 1/5] target/ppc: Add support for the Processor Attention instruction Date: Thu, 31 Mar 2022 11:58:09 -0300 Message-Id: <20220331145813.21719-2-leandro.lupori@eldorado.org.br> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220331145813.21719-1-leandro.lupori@eldorado.org.br> References: <20220331145813.21719-1-leandro.lupori@eldorado.org.br> MIME-Version: 1.0 X-OriginalArrivalTime: 31 Mar 2022 15:24:02.0531 (UTC) FILETIME=[5A12DB30:01D84513] X-Host-Lookup-Failed: Reverse DNS lookup failed for 187.72.171.209 (failed) Received-SPF: pass client-ip=187.72.171.209; envelope-from=leandro.lupori@eldorado.org.br; helo=outlook.eldorado.org.br X-Spam_score_int: -4 X-Spam_score: -0.5 X-Spam_bar: / X-Spam_report: (-0.5 / 5.0 requ) BAYES_00=-1.9, PDS_HP_HELO_NORDNS=0.659, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Leandro Lupori , danielhb413@gmail.com, richard.henderson@linaro.org, groug@kaod.org, clg@kaod.org, pbonzini@redhat.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Cédric Le Goater Check the HID0 bit to send signal, currently modeled as a checkstop. The QEMU implementation adds an exit using the GPR[3] value (that's a hack for tests) Signed-off-by: Cédric Le Goater Signed-off-by: Leandro Lupori --- target/ppc/cpu.h | 8 ++++++++ target/ppc/excp_helper.c | 27 +++++++++++++++++++++++++++ target/ppc/helper.h | 1 + target/ppc/translate.c | 14 ++++++++++++++ 4 files changed, 50 insertions(+) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 047b24ba50..12f9f3a880 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -173,6 +173,12 @@ enum { POWERPC_EXCP_PRIV_REG = 0x02, /* Privileged register exception */ /* Trap */ POWERPC_EXCP_TRAP = 0x40, + /* Processor Attention */ + POWERPC_EXCP_ATTN = 0x100, + /* + * NOTE: POWERPC_EXCP_ATTN uses values from 0x100 to 0x1ff to return + * error codes. + */ }; #define PPC_INPUT(env) ((env)->bus_model) @@ -2089,6 +2095,8 @@ void ppc_compat_add_property(Object *obj, const char *name, #define HID0_DOZE (1 << 23) /* pre-2.06 */ #define HID0_NAP (1 << 22) /* pre-2.06 */ #define HID0_HILE PPC_BIT(19) /* POWER8 */ +#define HID0_ATTN PPC_BIT(31) /* Processor Attention */ +#define HID0_POWER9_ATTN PPC_BIT(3) #define HID0_POWER9_HILE PPC_BIT(4) /*****************************************************************************/ diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index d3e2cfcd71..b0c629905c 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1379,6 +1379,9 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) } cs->halted = 1; cpu_interrupt_exittb(cs); + if ((env->error_code & ~0xff) == POWERPC_EXCP_ATTN) { + exit(env->error_code & 0xff); + } } if (env->msr_mask & MSR_HVB) { /* @@ -1971,6 +1974,30 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn) env->resume_as_sreset = (insn != PPC_PM_STOP) || (env->spr[SPR_PSSCR] & PSSCR_EC); } + +/* + * Processor Attention instruction (Implementation dependent) + */ +void helper_attn(CPUPPCState *env, target_ulong r3) +{ + bool attn = false; + + if (env->excp_model == POWERPC_EXCP_POWER8) { + attn = !!(env->spr[SPR_HID0] & HID0_ATTN); + } else if (env->excp_model == POWERPC_EXCP_POWER9 || + env->excp_model == POWERPC_EXCP_POWER10) { + attn = !!(env->spr[SPR_HID0] & HID0_POWER9_ATTN); + } + + if (attn) { + raise_exception_err(env, POWERPC_EXCP_MCHECK, + POWERPC_EXCP_ATTN | (r3 & 0xff)); + } else { + raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, + POWERPC_EXCP_INVAL | + POWERPC_EXCP_INVAL_INVAL, GETPC()); + } +} #endif /* defined(TARGET_PPC64) */ static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 57da11c77e..9a2497569b 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -14,6 +14,7 @@ DEF_HELPER_1(rfmci, void, env) #if defined(TARGET_PPC64) DEF_HELPER_2(scv, noreturn, env, i32) DEF_HELPER_2(pminsn, void, env, i32) +DEF_HELPER_2(attn, void, env, tl) DEF_HELPER_1(rfid, void, env) DEF_HELPER_1(rfscv, void, env) DEF_HELPER_1(hrfid, void, env) diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 408ae26173..5ace6f3a29 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -4123,6 +4123,19 @@ static void gen_rvwinkle(DisasContext *ctx) gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next); #endif /* defined(CONFIG_USER_ONLY) */ } + +static void gen_attn(DisasContext *ctx) +{ + #if defined(CONFIG_USER_ONLY) + GEN_PRIV; +#else + CHK_SV; + + gen_helper_attn(cpu_env, cpu_gpr[3]); + ctx->base.is_jmp = DISAS_NORETURN; +#endif +} + #endif /* #if defined(TARGET_PPC64) */ static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip) @@ -6844,6 +6857,7 @@ GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), GEN_HANDLER_E(sleep, 0x13, 0x12, 0x0e, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206), GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H), +GEN_HANDLER(attn, 0x0, 0x00, 0x8, 0xfffffdff, PPC_FLOW), #endif /* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */ GEN_HANDLER(sc, 0x11, 0x11, 0xFF, 0x03FFF01D, PPC_FLOW), From patchwork Thu Mar 31 14:58:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Leandro Lupori X-Patchwork-Id: 1611828 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) 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 bilbo.ozlabs.org (Postfix) with ESMTPS id 4KTnQN36dZz9sGM for ; Fri, 1 Apr 2022 02:33:48 +1100 (AEDT) Received: from localhost ([::1]:53832 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nZwny-0002OW-Fg for incoming@patchwork.ozlabs.org; Thu, 31 Mar 2022 11:33:46 -0400 Received: from eggs.gnu.org ([209.51.188.92]:56364) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nZwfl-0003rW-0e; Thu, 31 Mar 2022 11:25:17 -0400 Received: from [187.72.171.209] (port=51585 helo=outlook.eldorado.org.br) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nZwfd-0004ne-Kk; Thu, 31 Mar 2022 11:25:15 -0400 Received: from p9ibm ([10.10.71.235]) by outlook.eldorado.org.br over TLS secured channel with Microsoft SMTPSVC(8.5.9600.16384); Thu, 31 Mar 2022 12:24:02 -0300 Received: from eldorado.org.br (unknown [10.10.70.45]) by p9ibm (Postfix) with ESMTP id 31F18800F41; Thu, 31 Mar 2022 11:58:43 -0300 (-03) From: Leandro Lupori To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Subject: [RFC PATCH v2 2/5] ppc/pnv: Activate support for the Processor Attention instruction Date: Thu, 31 Mar 2022 11:58:10 -0300 Message-Id: <20220331145813.21719-3-leandro.lupori@eldorado.org.br> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220331145813.21719-1-leandro.lupori@eldorado.org.br> References: <20220331145813.21719-1-leandro.lupori@eldorado.org.br> MIME-Version: 1.0 X-OriginalArrivalTime: 31 Mar 2022 15:24:02.0687 (UTC) FILETIME=[5A2AA8F0:01D84513] X-Host-Lookup-Failed: Reverse DNS lookup failed for 187.72.171.209 (failed) Received-SPF: pass client-ip=187.72.171.209; envelope-from=leandro.lupori@eldorado.org.br; helo=outlook.eldorado.org.br X-Spam_score_int: -4 X-Spam_score: -0.5 X-Spam_bar: / X-Spam_report: (-0.5 / 5.0 requ) BAYES_00=-1.9, PDS_HP_HELO_NORDNS=0.659, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Leandro Lupori , danielhb413@gmail.com, richard.henderson@linaro.org, groug@kaod.org, clg@kaod.org, pbonzini@redhat.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Cédric Le Goater Signed-off-by: Cédric Le Goater Signed-off-by: Leandro Lupori --- hw/ppc/pnv_core.c | 6 ++++++ include/hw/ppc/pnv_core.h | 1 + 2 files changed, 7 insertions(+) diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 19e8eb885f..eb59b44a6c 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -46,6 +46,7 @@ static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu) CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip); + PnvCoreClass *pcorec = PNV_CORE_GET_CLASS(pc); cpu_reset(cs); @@ -57,6 +58,8 @@ static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu) env->nip = 0x10; env->msr |= MSR_HVB; /* Hypervisor mode */ env->spr[SPR_HRMOR] = pc->hrmor; + env->spr[SPR_HID0] |= pcorec->attn; + hreg_compute_hflags(env); pcc->intc_reset(pc->chip, cpu); @@ -300,6 +303,7 @@ static void pnv_core_power8_class_init(ObjectClass *oc, void *data) PnvCoreClass *pcc = PNV_CORE_CLASS(oc); pcc->xscom_ops = &pnv_core_power8_xscom_ops; + pcc->attn = HID0_ATTN; } static void pnv_core_power9_class_init(ObjectClass *oc, void *data) @@ -307,6 +311,7 @@ static void pnv_core_power9_class_init(ObjectClass *oc, void *data) PnvCoreClass *pcc = PNV_CORE_CLASS(oc); pcc->xscom_ops = &pnv_core_power9_xscom_ops; + pcc->attn = HID0_POWER9_ATTN; } static void pnv_core_power10_class_init(ObjectClass *oc, void *data) @@ -315,6 +320,7 @@ static void pnv_core_power10_class_init(ObjectClass *oc, void *data) /* TODO: Use the P9 XSCOMs for now on P10 */ pcc->xscom_ops = &pnv_core_power9_xscom_ops; + pcc->attn = HID0_POWER9_ATTN; } static void pnv_core_class_init(ObjectClass *oc, void *data) diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index c22eab2e1f..04e1fec1f3 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -47,6 +47,7 @@ struct PnvCoreClass { DeviceClass parent_class; const MemoryRegionOps *xscom_ops; + uint64_t attn; }; #define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE From patchwork Thu Mar 31 14:58:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Leandro Lupori X-Patchwork-Id: 1611829 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) 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 bilbo.ozlabs.org (Postfix) with ESMTPS id 4KTnQT1ym0z9sGG for ; Fri, 1 Apr 2022 02:33:53 +1100 (AEDT) Received: from localhost ([::1]:54324 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nZwo3-0002i2-9l for incoming@patchwork.ozlabs.org; Thu, 31 Mar 2022 11:33:51 -0400 Received: from eggs.gnu.org ([209.51.188.92]:56156) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nZwfM-00034L-Io; Thu, 31 Mar 2022 11:24:52 -0400 Received: from [187.72.171.209] (port=51585 helo=outlook.eldorado.org.br) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nZwfJ-0004ne-OX; Thu, 31 Mar 2022 11:24:52 -0400 Received: from p9ibm ([10.10.71.235]) by outlook.eldorado.org.br over TLS secured channel with Microsoft SMTPSVC(8.5.9600.16384); Thu, 31 Mar 2022 12:24:02 -0300 Received: from eldorado.org.br (unknown [10.10.70.45]) by p9ibm (Postfix) with ESMTP id 7992E8010D7; Thu, 31 Mar 2022 11:58:43 -0300 (-03) From: Leandro Lupori To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Subject: [RFC PATCH v2 3/5] tests/tcg/ppc64: add basic softmmu test support Date: Thu, 31 Mar 2022 11:58:11 -0300 Message-Id: <20220331145813.21719-4-leandro.lupori@eldorado.org.br> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220331145813.21719-1-leandro.lupori@eldorado.org.br> References: <20220331145813.21719-1-leandro.lupori@eldorado.org.br> MIME-Version: 1.0 X-OriginalArrivalTime: 31 Mar 2022 15:24:02.0390 (UTC) FILETIME=[59FD5760:01D84513] X-Host-Lookup-Failed: Reverse DNS lookup failed for 187.72.171.209 (failed) Received-SPF: pass client-ip=187.72.171.209; envelope-from=leandro.lupori@eldorado.org.br; helo=outlook.eldorado.org.br X-Spam_score_int: -4 X-Spam_score: -0.5 X-Spam_bar: / X-Spam_report: (-0.5 / 5.0 requ) BAYES_00=-1.9, PDS_HP_HELO_NORDNS=0.659, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Leandro Lupori , danielhb413@gmail.com, richard.henderson@linaro.org, groug@kaod.org, clg@kaod.org, pbonzini@redhat.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Add support to build and run the multiarch hello test, that simply prints a message and exits. The linker script, console code and related header files were imported from https://github.com/legoater/pnv-test, that are the Microwatt tests adapted to use a PowerNV console. Some other changes were made on top of these, mainly on boot.S, that was based on pnv-test/mmu/head.S, to better integrate with QEMU test infrastructure. Signed-off-by: Leandro Lupori --- MAINTAINERS | 2 + tests/tcg/ppc64/Makefile.softmmu-target | 59 ++++++++ tests/tcg/ppc64/system/include/asm.h | 62 ++++++++ tests/tcg/ppc64/system/include/console.h | 15 ++ tests/tcg/ppc64/system/include/io.h | 61 ++++++++ tests/tcg/ppc64/system/include/pnv.h | 21 +++ tests/tcg/ppc64/system/include/uart.h | 54 +++++++ tests/tcg/ppc64/system/lib/boot.S | 68 +++++++++ tests/tcg/ppc64/system/lib/console.c | 173 +++++++++++++++++++++++ tests/tcg/ppc64/system/lib/powerpc.lds | 27 ++++ 10 files changed, 542 insertions(+) create mode 100644 tests/tcg/ppc64/Makefile.softmmu-target create mode 100644 tests/tcg/ppc64/system/include/asm.h create mode 100644 tests/tcg/ppc64/system/include/console.h create mode 100644 tests/tcg/ppc64/system/include/io.h create mode 100644 tests/tcg/ppc64/system/include/pnv.h create mode 100644 tests/tcg/ppc64/system/include/uart.h create mode 100644 tests/tcg/ppc64/system/lib/boot.S create mode 100644 tests/tcg/ppc64/system/lib/console.c create mode 100644 tests/tcg/ppc64/system/lib/powerpc.lds diff --git a/MAINTAINERS b/MAINTAINERS index cc364afef7..e8fde33562 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -266,6 +266,7 @@ M: Cédric Le Goater M: Daniel Henrique Barboza R: David Gibson R: Greg Kurz +R: Leandro Lupori L: qemu-ppc@nongnu.org S: Maintained F: target/ppc/ @@ -273,6 +274,7 @@ F: hw/ppc/ppc.c F: hw/ppc/ppc_booke.c F: include/hw/ppc/ppc.h F: disas/ppc.c +F: tests/tcg/ppc64/ RISC-V TCG CPUs M: Palmer Dabbelt diff --git a/tests/tcg/ppc64/Makefile.softmmu-target b/tests/tcg/ppc64/Makefile.softmmu-target new file mode 100644 index 0000000000..8f9925ca5a --- /dev/null +++ b/tests/tcg/ppc64/Makefile.softmmu-target @@ -0,0 +1,59 @@ +# +# PowerPC64 system tests +# + +# For now, disable tests that are failing +DISABLED_TESTS := memory +DISABLED_EXTRA_RUNS := run-gdbstub-memory + +PPC64_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/ppc64/system +VPATH+=$(PPC64_SYSTEM_SRC) + +# These objects provide the basic boot code and helper functions for all tests +CRT_PATH=$(PPC64_SYSTEM_SRC)/lib +CRT_OBJS=boot.o console.o + +PPC64_TEST_SRCS=$(wildcard $(PPC64_SYSTEM_SRC)/*.c) +PPC64_TESTS=$(patsubst $(PPC64_SYSTEM_SRC)/%.c, %, $(PPC64_TEST_SRCS)) + +LINK_SCRIPT=$(CRT_PATH)/powerpc.lds +# NOTE: --build-id is stored before the first code section in the linked +# binary, which causes problems for most tests, that expect to +# begin at address 0. +LDFLAGS=-Wl,-T$(LINK_SCRIPT) -Wl,--build-id=none -static -nostdlib \ + $(CRT_OBJS) $(MINILIB_OBJS) -lgcc +TESTS += $(filter-out $(DISABLED_TESTS),$(PPC64_TESTS) $(MULTIARCH_TESTS)) +EXTRA_RUNS += $(filter-out $(DISABLED_EXTRA_RUNS),$(MULTIARCH_RUNS)) + +# NOTE: -Os doesn't work well with -Wl,--oformat=binary +# Some linker generated functions, such as savegpr*/restgpr*, +# end up being undefined. +CFLAGS = -O -g -Wall -std=c99 -msoft-float -mno-vsx -mno-altivec \ + -fno-stack-protector -ffreestanding \ + -I $(PPC64_SYSTEM_SRC)/include $(MINILIB_INC) \ + -mcpu=power8 + +# Leave the .elf files, to make debugging easier +.PRECIOUS: $(CRT_OBJS) $(addsuffix .elf,$(TESTS)) + +# Build CRT objects +%.o: $(CRT_PATH)/%.S + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@ + +%.o: $(CRT_PATH)/%.c + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@ + +# Build and link the tests + +# The .elf files are just for debugging +%.elf: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS) + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) + +%: %.c %.elf $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS) + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) -Wl,--oformat=binary + +memory: CFLAGS+=-DCHECK_UNALIGNED=1 + +# Running +QEMU_BASE_MACHINE=-cpu power9 -M powernv9 -m 1G -vga none -nographic +QEMU_OPTS+=$(QEMU_BASE_MACHINE) -serial chardev:output -bios diff --git a/tests/tcg/ppc64/system/include/asm.h b/tests/tcg/ppc64/system/include/asm.h new file mode 100644 index 0000000000..60bc08cd5c --- /dev/null +++ b/tests/tcg/ppc64/system/include/asm.h @@ -0,0 +1,62 @@ +#ifndef PPC64_ASM_H +#define PPC64_ASM_H + +#define XCONCAT(a, b) a ## b +#define CONCAT(a, b) XCONCAT(a, b) + +/* Load an immediate 64-bit value into a register */ +#define LOAD_IMM64(r, e) \ + lis r, (e)@highest; \ + ori r, r, (e)@higher; \ + rldicr r, r, 32, 31; \ + oris r, r, (e)@h; \ + ori r, r, (e)@l; + +/* Switch CPU to little-endian mode, if needed */ +#define FIXUP_ENDIAN \ + tdi 0, 0, 0x48; /* Reverse endian of b . + 8 */ \ + b $ + 44; /* Skip trampoline if endian is good */ \ + .long 0xa600607d; /* mfmsr r11 */ \ + .long 0x01006b69; /* xori r11,r11,1 */ \ + .long 0x00004039; /* li r10,0 */ \ + .long 0x6401417d; /* mtmsrd r10,1 */ \ + .long 0x05009f42; /* bcl 20,31,$+4 */ \ + .long 0xa602487d; /* mflr r10 */ \ + .long 0x14004a39; /* addi r10,r10,20 */ \ + .long 0xa6035a7d; /* mtsrr0 r10 */ \ + .long 0xa6037b7d; /* mtsrr1 r11 */ \ + .long 0x2400004c /* rfid */ + +/* Handle differences between ELFv1 and ELFv2 ABIs */ + +#define DOT_LABEL(name) CONCAT(., name) + +#if !defined(_CALL_ELF) || _CALL_ELF == 1 +#define FUNCTION(name) \ + .section ".opd", "aw"; \ + .p2align 3; \ + .globl name; \ +name: \ + .quad DOT_LABEL(name), .TOC.@tocbase, 0; \ + .previous; \ +DOT_LABEL(name): + +#define CALL(fn) \ + LOAD_IMM64(%r12, fn); \ + ld %r12, 0(%r12); \ + mtctr %r12; \ + bctrl + +#else +#define FUNCTION(name) \ + .globl name; \ +name: + +#define CALL(fn) \ + LOAD_IMM64(%r12, fn); \ + mtctr %r12; \ + bctrl + +#endif + +#endif diff --git a/tests/tcg/ppc64/system/include/console.h b/tests/tcg/ppc64/system/include/console.h new file mode 100644 index 0000000000..37ea45827b --- /dev/null +++ b/tests/tcg/ppc64/system/include/console.h @@ -0,0 +1,15 @@ +#ifndef PPC64_CONSOLE_H +#define PPC64_CONSOLE_H + +#include +#include + +void console_init(void); +void console_set_irq_en(bool rx_irq, bool tx_irq); +int getchar(void); +int putchar(int c); +int puts(const char *str); + +size_t strlen(const char *s); + +#endif diff --git a/tests/tcg/ppc64/system/include/io.h b/tests/tcg/ppc64/system/include/io.h new file mode 100644 index 0000000000..92932a5b75 --- /dev/null +++ b/tests/tcg/ppc64/system/include/io.h @@ -0,0 +1,61 @@ +#ifndef PPC64_IO_H +#define PPC64_IO_H + +static inline uint8_t readb(unsigned long addr) +{ + uint8_t val; + __asm__ volatile("sync; lbzcix %0,0,%1" + : "=r" (val) : "r" (addr) : "memory"); + return val; +} + +static inline uint16_t readw(unsigned long addr) +{ + uint16_t val; + __asm__ volatile("sync; lhzcix %0,0,%1" + : "=r" (val) : "r" (addr) : "memory"); + return val; +} + +static inline uint32_t readl(unsigned long addr) +{ + uint32_t val; + __asm__ volatile("sync; lwzcix %0,0,%1" + : "=r" (val) : "r" (addr) : "memory"); + return val; +} + +static inline uint64_t readq(unsigned long addr) +{ + uint64_t val; + __asm__ volatile("sync; ldcix %0,0,%1" + : "=r" (val) : "r" (addr) : "memory"); + return val; +} + +static inline void writeb(uint8_t val, unsigned long addr) +{ + __asm__ volatile("sync; stbcix %0,0,%1" + : : "r" (val), "r" (addr) : "memory"); +} + +static inline void writew(uint16_t val, unsigned long addr) +{ + __asm__ volatile("sync; sthcix %0,0,%1" + : : "r" (val), "r" (addr) : "memory"); +} + +static inline void writel(uint32_t val, unsigned long addr) +{ + __asm__ volatile("sync; stwcix %0,0,%1" + : : "r" (val), "r" (addr) : "memory"); +} + +static inline void writeq(uint64_t val, unsigned long addr) +{ + __asm__ volatile("sync; stdcix %0,0,%1" + : : "r" (val), "r" (addr) : "memory"); +} + +#endif /* PPC64_IO_H */ + diff --git a/tests/tcg/ppc64/system/include/pnv.h b/tests/tcg/ppc64/system/include/pnv.h new file mode 100644 index 0000000000..0990a9fad9 --- /dev/null +++ b/tests/tcg/ppc64/system/include/pnv.h @@ -0,0 +1,21 @@ +#ifndef PPC64_PNV_H +#define PPC64_PNV_H + +#define LPC_BASE_ADDR 0x0006030000000000 +#define LPC_IO_SPACE 0xd0010000 +#define LPC_FW_SPACE 0xf0000000 + +#define UART_BASE (LPC_BASE_ADDR + LPC_IO_SPACE + 0x3f8); + +#define MSR_HV (1ULL << (63 - 3)) + +static inline bool is_pnv() +{ + unsigned long msr; + + __asm__ volatile ("mfmsr %0" + : "=r" (msr) + : : "memory"); + return !!(msr & MSR_HV); +} +#endif diff --git a/tests/tcg/ppc64/system/include/uart.h b/tests/tcg/ppc64/system/include/uart.h new file mode 100644 index 0000000000..77610e2ec2 --- /dev/null +++ b/tests/tcg/ppc64/system/include/uart.h @@ -0,0 +1,54 @@ +#ifndef PPC64_UART_H +#define PPC64_UART_H + +/* + * Register definitions for our standard (16550 style) UART + */ +#define UART_REG_RX 0x00 +#define UART_REG_TX 0x00 +#define UART_REG_DLL 0x00 +#define UART_REG_IER 0x04 +#define UART_REG_IER_RDI 0x01 +#define UART_REG_IER_THRI 0x02 +#define UART_REG_IER_RLSI 0x04 +#define UART_REG_IER_MSI 0x08 +#define UART_REG_DLM 0x04 +#define UART_REG_IIR 0x08 +#define UART_REG_FCR 0x08 +#define UART_REG_FCR_EN_FIFO 0x01 +#define UART_REG_FCR_CLR_RCVR 0x02 +#define UART_REG_FCR_CLR_XMIT 0x04 +#define UART_REG_FCR_TRIG1 0x00 +#define UART_REG_FCR_TRIG4 0x40 +#define UART_REG_FCR_TRIG8 0x80 +#define UART_REG_FCR_TRIG14 0xc0 +#define UART_REG_LCR 0x0c +#define UART_REG_LCR_5BIT 0x00 +#define UART_REG_LCR_6BIT 0x01 +#define UART_REG_LCR_7BIT 0x02 +#define UART_REG_LCR_8BIT 0x03 +#define UART_REG_LCR_STOP 0x04 +#define UART_REG_LCR_PAR 0x08 +#define UART_REG_LCR_EVEN_PAR 0x10 +#define UART_REG_LCR_STIC_PAR 0x20 +#define UART_REG_LCR_BREAK 0x40 +#define UART_REG_LCR_DLAB 0x80 +#define UART_REG_MCR 0x10 +#define UART_REG_MCR_DTR 0x01 +#define UART_REG_MCR_RTS 0x02 +#define UART_REG_MCR_OUT1 0x04 +#define UART_REG_MCR_OUT2 0x08 +#define UART_REG_MCR_LOOP 0x10 +#define UART_REG_LSR 0x14 +#define UART_REG_LSR_DR 0x01 +#define UART_REG_LSR_OE 0x02 +#define UART_REG_LSR_PE 0x04 +#define UART_REG_LSR_FE 0x08 +#define UART_REG_LSR_BI 0x10 +#define UART_REG_LSR_THRE 0x20 +#define UART_REG_LSR_TEMT 0x40 +#define UART_REG_LSR_FIFOE 0x80 +#define UART_REG_MSR 0x18 +#define UART_REG_SCR 0x1c + +#endif diff --git a/tests/tcg/ppc64/system/lib/boot.S b/tests/tcg/ppc64/system/lib/boot.S new file mode 100644 index 0000000000..607945fba4 --- /dev/null +++ b/tests/tcg/ppc64/system/lib/boot.S @@ -0,0 +1,68 @@ +/* Copyright 2013-2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "asm.h" + +#define SPR_HID0 0x3f0 +#define SPR_HID0_POWER9_HILE 0x0800000000000000 + + .section ".head","ax" + + /* Microwatt currently enters in LE mode at 0x0 */ + . = 0 +_start: + b start + + /* QEMU enters in BE at 0x10 by default */ + . = 0x10 +.global start +start: + FIXUP_ENDIAN + + /* Setup TOC */ + LOAD_IMM64(%r2, .TOC.) + + /* Configure interrupt endian */ +#ifdef __LITTLE_ENDIAN__ + mfspr %r10, SPR_HID0 + LOAD_IMM64(%r11, SPR_HID0_POWER9_HILE) + or %r10, %r10, %r11 + mtspr SPR_HID0, %r10 +#endif + + /* Clear .bss */ + LOAD_IMM64(%r10,__bss_start) + LOAD_IMM64(%r11,__bss_end) + subf %r11,%r10,%r11 + addi %r11,%r11,63 + srdi. %r11,%r11,6 + beq 2f + mtctr %r11 +1: dcbz 0,%r10 + addi %r10,%r10,64 + bdnz 1b + + /* Setup stack */ +2: LOAD_IMM64(%r1,__stack_top) + li %r0,0 + stdu %r0,-16(%r1) + + CALL(console_init) + CALL(main) + + /* Terminate on exit */ + attn + b . diff --git a/tests/tcg/ppc64/system/lib/console.c b/tests/tcg/ppc64/system/lib/console.c new file mode 100644 index 0000000000..a4d8b02e21 --- /dev/null +++ b/tests/tcg/ppc64/system/lib/console.c @@ -0,0 +1,173 @@ +#include +#include + +#include "console.h" +#include "pnv.h" +#include "io.h" +#include "uart.h" + +#define UART_BAUDS 115200 +#define H_PUT_TERM_CHAR 88 + +/* + * Core UART functions to implement for a port + */ + +static uint64_t uart_base; + +struct console_ops { + int (*putchar)(int c); +} ops; + + +static unsigned long uart_divisor(unsigned long uart_freq, unsigned long bauds) +{ + return uart_freq / (bauds * 16); +} + +static bool std_uart_rx_empty(void) +{ + return !(readb(uart_base + UART_REG_LSR) & UART_REG_LSR_DR); +} + +static uint8_t std_uart_read(void) +{ + return readb(uart_base + UART_REG_RX); +} + +static bool std_uart_tx_full(void) +{ + /* TODO: check UART LSR */ + return 0; +} + +static void std_uart_write(uint8_t c) +{ + writeb(c, uart_base + UART_REG_TX); +} + +static void std_uart_set_irq_en(bool rx_irq, bool tx_irq) +{ + uint8_t ier = 0; + + if (tx_irq) { + ier |= UART_REG_IER_THRI; + } + if (rx_irq) { + ier |= UART_REG_IER_RDI; + } + writeb(ier, uart_base + UART_REG_IER); +} + +static void std_uart_init(uint64_t uart_freq) +{ + unsigned long div = uart_divisor(uart_freq, UART_BAUDS); + + writeb(UART_REG_LCR_DLAB, uart_base + UART_REG_LCR); + writeb(div & 0xff, uart_base + UART_REG_DLL); + writeb(div >> 8, uart_base + UART_REG_DLM); + writeb(UART_REG_LCR_8BIT, uart_base + UART_REG_LCR); + writeb(UART_REG_MCR_DTR | + UART_REG_MCR_RTS, uart_base + UART_REG_MCR); + writeb(UART_REG_FCR_EN_FIFO | + UART_REG_FCR_CLR_RCVR | + UART_REG_FCR_CLR_XMIT, uart_base + UART_REG_FCR); +} + +int getchar(void) +{ + while (std_uart_rx_empty()) { + ; /* Do nothing */ + } + return std_uart_read(); +} + +int putchar(int c) +{ + return ops.putchar(c); +} + +void __sys_outc(char c) +{ + putchar(c); +} + +static int putchar_uart(int c) +{ + while (std_uart_tx_full()) { + ; /* Do Nothing */ + } + std_uart_write(c); + return c; +} + +static int putchar_hvc(int c) +{ + register unsigned long hcall __asm__("r3") = H_PUT_TERM_CHAR; + register unsigned long termno __asm__("r4") = 0; + register unsigned long length __asm__("r5") = 1; + register unsigned long str __asm__("r6") = __builtin_bswap64(c); + + __asm__ volatile ("sc 1" : : "r" (hcall), "r" (termno), "r" (length), + "r" (str) : ); + return c; +} + +int puts(const char *str) +{ + unsigned int i; + + for (i = 0; *str; i++) { + char c = *(str++); + if (c == 10) { + putchar(13); + } + putchar(c); + } + return 0; +} + +size_t strlen(const char *s) +{ + size_t len = 0; + + while (*s++) { + len++; + } + + return len; +} + +struct console_ops pseries_console = { + .putchar = putchar_hvc, +}; + +struct console_ops pnv_console = { + .putchar = putchar_uart, +}; + +void uart_init(void) +{ + uint64_t proc_freq; /* TODO */ + + proc_freq = 0; /* TODO */ + + uart_base = UART_BASE + + std_uart_init(proc_freq); +} + +void console_init(void) +{ + if (is_pnv()) { + ops = pnv_console; + uart_init(); + } else { + ops = pseries_console; + } +} + +void console_set_irq_en(bool rx_irq, bool tx_irq) +{ + std_uart_set_irq_en(rx_irq, tx_irq); +} diff --git a/tests/tcg/ppc64/system/lib/powerpc.lds b/tests/tcg/ppc64/system/lib/powerpc.lds new file mode 100644 index 0000000000..db451e1fb9 --- /dev/null +++ b/tests/tcg/ppc64/system/lib/powerpc.lds @@ -0,0 +1,27 @@ +SECTIONS +{ + . = 0; + _start = .; + .head : { + KEEP(*(.head)) + } + . = ALIGN(0x1000); + .text : { *(.text) *(.text.*) *(.rodata) *(.rodata.*) } + . = ALIGN(0x1000); + .data : { *(.data) *(.data.*) *(.got) *(.toc) } + . = ALIGN(0x80); + __bss_start = .; + .bss : { + *(.dynsbss) + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(.common) + *(.bss.*) + } + . = ALIGN(0x80); + __bss_end = .; + . = . + 0x4000; + __stack_top = .; +} From patchwork Thu Mar 31 14:58:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leandro Lupori X-Patchwork-Id: 1611830 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) 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 bilbo.ozlabs.org (Postfix) with ESMTPS id 4KTnTq5v3yz9sGG for ; Fri, 1 Apr 2022 02:36:47 +1100 (AEDT) Received: from localhost ([::1]:60942 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nZwqq-0007Bk-Qu for incoming@patchwork.ozlabs.org; Thu, 31 Mar 2022 11:36:44 -0400 Received: from eggs.gnu.org ([209.51.188.92]:56182) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nZwfQ-0003Id-OL; Thu, 31 Mar 2022 11:24:56 -0400 Received: from [187.72.171.209] (port=51585 helo=outlook.eldorado.org.br) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nZwfN-0004ne-FK; Thu, 31 Mar 2022 11:24:56 -0400 Received: from p9ibm ([10.10.71.235]) by outlook.eldorado.org.br over TLS secured channel with Microsoft SMTPSVC(8.5.9600.16384); Thu, 31 Mar 2022 12:24:02 -0300 Received: from eldorado.org.br (unknown [10.10.70.45]) by p9ibm (Postfix) with ESMTP id D9224801476; Thu, 31 Mar 2022 11:58:43 -0300 (-03) From: Leandro Lupori To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Subject: [RFC PATCH v2 4/5] tests/tcg/ppc64: add MMU test sources Date: Thu, 31 Mar 2022 11:58:12 -0300 Message-Id: <20220331145813.21719-5-leandro.lupori@eldorado.org.br> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220331145813.21719-1-leandro.lupori@eldorado.org.br> References: <20220331145813.21719-1-leandro.lupori@eldorado.org.br> MIME-Version: 1.0 X-OriginalArrivalTime: 31 Mar 2022 15:24:02.0437 (UTC) FILETIME=[5A048350:01D84513] X-Host-Lookup-Failed: Reverse DNS lookup failed for 187.72.171.209 (failed) Received-SPF: pass client-ip=187.72.171.209; envelope-from=leandro.lupori@eldorado.org.br; helo=outlook.eldorado.org.br X-Spam_score_int: -4 X-Spam_score: -0.5 X-Spam_bar: / X-Spam_report: (-0.5 / 5.0 requ) BAYES_00=-1.9, PDS_HP_HELO_NORDNS=0.659, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Leandro Lupori , danielhb413@gmail.com, richard.henderson@linaro.org, groug@kaod.org, clg@kaod.org, pbonzini@redhat.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Add MMU test sources, from https://github.com/legoater/pnv-test, based on Microwatt tests but with some adaptations. In particular, the tests that check updates to RC bits were removed, because, apparently, Microwatt never updates RC bits, but just raise an exception when they must be updated, leaving the task to the OS (https://github.com/antonblanchard/microwatt/blob/master/mmu.vhdl#L402). Signed-off-by: Leandro Lupori --- tests/tcg/ppc64/system/mmu-head.S | 142 ++++++ tests/tcg/ppc64/system/mmu.c | 764 ++++++++++++++++++++++++++++++ tests/tcg/ppc64/system/mmu.h | 9 + 3 files changed, 915 insertions(+) create mode 100644 tests/tcg/ppc64/system/mmu-head.S create mode 100644 tests/tcg/ppc64/system/mmu.c create mode 100644 tests/tcg/ppc64/system/mmu.h diff --git a/tests/tcg/ppc64/system/mmu-head.S b/tests/tcg/ppc64/system/mmu-head.S new file mode 100644 index 0000000000..a3f23fcb17 --- /dev/null +++ b/tests/tcg/ppc64/system/mmu-head.S @@ -0,0 +1,142 @@ +/* Copyright 2013-2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "asm.h" + +#include "lib/boot.S" + + /* Read a location with translation on */ +FUNCTION(test_read) + mfmsr %r9 + ori %r8,%r9,0x10 /* set MSR_DR */ + mtmsrd %r8,0 + mr %r6,%r3 + li %r3,0 + ld %r5,0(%r6) + li %r3,1 + /* land here if DSI occurred */ + mtmsrd %r9,0 + std %r5,0(%r4) + blr + + /* Write a location with translation on */ +FUNCTION(test_write) + mfmsr %r9 + ori %r8,%r9,0x10 /* set MSR_DR */ + mtmsrd %r8,0 + mr %r6,%r3 + li %r3,0 + std %r4,0(%r6) + li %r3,1 + /* land here if DSI occurred */ + mtmsrd %r9,0 + blr + + /* Do a dcbz with translation on */ +FUNCTION(test_dcbz) + mfmsr %r9 + ori %r8,%r9,0x10 /* set MSR_DR */ + mtmsrd %r8,0 + mr %r6,%r3 + li %r3,0 + dcbz 0,%r6 + li %r3,1 + /* land here if DSI occurred */ + mtmsrd %r9,0 + blr + +FUNCTION(test_exec) + mtsrr0 %r4 + mtsrr1 %r5 + rfid + +#define EXCEPTION(nr) \ + .= nr ;\ + li %r3, (nr >> 4) ;\ + attn + + /* DSI vector - skip the failing instruction + the next one */ + . = 0x300 + mtsprg0 %r10 + mfsrr0 %r10 + addi %r10,%r10,8 + mtsrr0 %r10 + rfid + + EXCEPTION(0x380) + + /* + * ISI vector - jump to LR to return from the test, + * with r3 cleared + */ + . = 0x400 + li %r3,0 + blr + + /* More exception stubs */ + EXCEPTION(0x480) + EXCEPTION(0x500) + EXCEPTION(0x600) + EXCEPTION(0x700) + EXCEPTION(0x800) + EXCEPTION(0x900) + EXCEPTION(0x980) + EXCEPTION(0xa00) + EXCEPTION(0xb00) + + /* + * System call - used to exit from tests where MSR[PR] + * may have been set. + */ + . = 0xc00 + blr + + EXCEPTION(0xd00) + EXCEPTION(0xe00) + EXCEPTION(0xe20) + EXCEPTION(0xe40) + EXCEPTION(0xe60) + EXCEPTION(0xe80) + EXCEPTION(0xf00) + EXCEPTION(0xf20) + EXCEPTION(0xf40) + EXCEPTION(0xf60) + EXCEPTION(0xf80) + + . = 0x1000 + /* + * This page gets mapped at various locations and + * the tests try to execute from it. + * r3 contains the test number. + */ +FUNCTION(test_start) + nop + nop + cmpdi %r3,1 + beq test_1 + cmpdi %r3,2 + beq test_2 +test_return: + li %r3,1 + sc + + . = 0x1ff8 + /* test a branch near the end of a page */ +test_1: b test_return + + /* test flowing from one page to the next */ +test_2: nop + b test_return diff --git a/tests/tcg/ppc64/system/mmu.c b/tests/tcg/ppc64/system/mmu.c new file mode 100644 index 0000000000..8e9fca2675 --- /dev/null +++ b/tests/tcg/ppc64/system/mmu.c @@ -0,0 +1,764 @@ +#include +#include +#include + +#include "minilib.h" +#include "mmu.h" + +#define MSR_LE 0x01 +#define MSR_DR 0x10 +#define MSR_IR 0x20 +#define MSR_HV 0x1000000000000000ul +#define MSR_SF 0x8000000000000000ul + +#ifdef __LITTLE_ENDIAN__ +#define MSR_DFLT (MSR_SF | MSR_HV | MSR_LE) +#else +#define MSR_DFLT (MSR_SF | MSR_HV) +#endif + +#define XSTR(x) #x +#define STR(x) XSTR(x) + +#define RIC_TLB 0 +#define RIC_PWC 1 +#define RIC_ALL 2 + +#define PRS 1 + +#define IS(x) ((unsigned long)(x) << 10) +#define IS_VA IS(0) +#define IS_PID IS(1) +#define IS_LPID IS(2) +#define IS_ALL IS(3) + +#define TLBIE_5(rb, rs, ric, prs, r) \ + __asm__ volatile(".long 0x7c000264 | " \ + "%0 << 21 | " \ + STR(ric) " << 18 | " \ + STR(prs) " << 17 | " \ + STR(r) "<< 16 | " \ + "%1 << 11" \ + : : "r" (rs), "r" (rb) : "memory") + +static inline void tlbie_all(int prs) +{ + if (prs) { + TLBIE_5(IS_ALL, 0, RIC_ALL, 1, 1); + } else { + TLBIE_5(IS_ALL, 0, RIC_ALL, 0, 1); + } +} + +static inline void tlbie_va(unsigned long va, int prs) +{ + va &= ~0xffful; + + if (prs) { + TLBIE_5(IS_VA | va, 0, RIC_TLB, 1, 1); + } else { + TLBIE_5(IS_VA | va, 0, RIC_TLB, 0, 1); + } + __asm__ volatile("eieio; tlbsync; ptesync" : : : "memory"); +} + +#define DSISR 18 +#define DAR 19 +#define SRR0 26 +#define SRR1 27 +#define PID 48 +#define LPCR 318 +#define PTCR 464 + +#define PPC_BIT(x) (0x8000000000000000ul >> (x)) + +#define LPCR_UPRT PPC_BIT(41) +#define LPCR_HR PPC_BIT(43) + +#define PATE_HR PPC_BIT(0) + +static inline unsigned long mfspr(int sprnum) +{ + long val; + + __asm__ volatile("mfspr %0,%1" : "=r" (val) : "i" (sprnum)); + return val; +} + +static inline void mtspr(int sprnum, unsigned long val) +{ + __asm__ volatile("mtspr %0,%1" : : "i" (sprnum), "r" (val)); +} + +static inline void store_pte(unsigned long *p, unsigned long pte) +{ +#ifdef __LITTLE_ENDIAN__ + __asm__ volatile("stdbrx %1,0,%0" : : "r" (p), "r" (pte) : "memory"); +#else + __asm__ volatile("stdx %1,0,%0" : : "r" (p), "r" (pte) : "memory"); +#endif + __asm__ volatile("ptesync" : : : "memory"); +} + +#define CACHE_LINE_SIZE 64 + +void zero_memory(void *ptr, unsigned long nbytes) +{ + unsigned long nb, i, nl; + void *p; + + for (; nbytes != 0; nbytes -= nb, ptr += nb) { + nb = -((unsigned long)ptr) & (CACHE_LINE_SIZE - 1); + if (nb == 0 && nbytes >= CACHE_LINE_SIZE) { + nl = nbytes / CACHE_LINE_SIZE; + p = ptr; + for (i = 0; i < nl; ++i) { + __asm__ volatile("dcbz 0,%0" : : "r" (p) : "memory"); + p += CACHE_LINE_SIZE; + } + nb = nl * CACHE_LINE_SIZE; + } else { + if (nb > nbytes) { + nb = nbytes; + } + for (i = 0; i < nb; ++i) { + ((unsigned char *)ptr)[i] = 0; + } + } + } +} + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1ul << PAGE_SHIFT) + +/* Partition Page Dir params */ +#define PPD_L1_BITS 5 +#define PPD_L2_BITS 14 /* virtual level 2 PGD address bits */ +#define PPD_PA_INC (1ul << (PAGE_SHIFT + PPD_L2_BITS)) + +#define RPTE_V PPC_BIT(0) +#define RPTE_L PPC_BIT(1) +#define RPTE_RPN_MASK 0x01fffffffffff000ul +#define RPTE_R PPC_BIT(55) +#define RPTE_C PPC_BIT(56) +#define RPTE_PRIV PPC_BIT(60) +#define RPTE_RD PPC_BIT(61) +#define RPTE_RW PPC_BIT(62) +#define RPTE_EX PPC_BIT(63) +#define RPTE_PERM_ALL (RPTE_RD | RPTE_RW | RPTE_EX) + +#define PERM_EX RPTE_EX +#define PERM_WR RPTE_RW +#define PERM_RD RPTE_RD +#define PERM_PRIV RPTE_PRIV +#define ATTR_NC 0x020 +#define CHG RPTE_C +#define REF RPTE_R + +#define DFLT_PERM (PERM_WR | PERM_RD | REF | CHG) + +/* + * Set up an MMU translation tree using memory starting at the 64k point. + * We use 2 levels, mapping 2GB (the minimum size possible), with a + * 8kB PGD level pointing to 4kB PTE pages. + */ +unsigned long *pgdir = (unsigned long *) 0x10000; +unsigned long *proc_tbl = (unsigned long *) 0x12000; +unsigned long *part_tbl = (unsigned long *) 0x13000; +unsigned long *part_pgdir = (unsigned long *) 0x14000; +unsigned long free_ptr = 0x15000; +void *eas_mapped[4]; +int neas_mapped; + +void init_mmu(void) +{ + int i, n; + unsigned long pa, pte; + + /* Select Radix MMU (HR), with HW process table */ + mtspr(LPCR, mfspr(LPCR) | LPCR_UPRT | LPCR_HR); + + /* + * Set up partition page dir, needed to translate process table + * addresses. + * We use only 1 level, mapping 2GB 1-1, with 32 64M pages. + */ + zero_memory(part_tbl, PAGE_SIZE); + store_pte(&part_tbl[0], PATE_HR | (unsigned long) part_pgdir | + PPD_L1_BITS); + + for (i = 0, n = 1 << PPD_L1_BITS, pa = 0; + i < n; i++, pa += PPD_PA_INC) { + pte = RPTE_V | RPTE_L | (pa & RPTE_RPN_MASK) | RPTE_PERM_ALL; + store_pte(&part_pgdir[i], pte); + } + + /* set up partition table */ + store_pte(&part_tbl[1], (unsigned long)proc_tbl); + /* set up process table */ + zero_memory(proc_tbl, 512 * sizeof(unsigned long)); + mtspr(PTCR, (unsigned long)part_tbl); + mtspr(PID, 1); + zero_memory(pgdir, 1024 * sizeof(unsigned long)); + /* RTS = 0 (2GB address space), RPDS = 10 (1024-entry top level) */ + store_pte(&proc_tbl[2 * 1], (unsigned long) pgdir | 10); + tlbie_all(0); /* invalidate all TLB entries */ +} + +static unsigned long *read_pgd(unsigned long i) +{ + unsigned long ret; + +#ifdef __LITTLE_ENDIAN__ + __asm__ volatile("ldbrx %0,%1,%2" : "=r" (ret) : "b" (pgdir), + "r" (i * sizeof(unsigned long))); +#else + __asm__ volatile("ldx %0,%1,%2" : "=r" (ret) : "b" (pgdir), + "r" (i * sizeof(unsigned long))); +#endif + return (unsigned long *) (ret & 0x00ffffffffffff00); +} + +void map(void *ea, void *pa, unsigned long perm_attr) +{ + unsigned long epn = (unsigned long) ea >> 12; + unsigned long i, j; + unsigned long *ptep; + + i = (epn >> 9) & 0x3ff; + j = epn & 0x1ff; + if (pgdir[i] == 0) { + zero_memory((void *)free_ptr, 512 * sizeof(unsigned long)); + store_pte(&pgdir[i], 0x8000000000000000 | free_ptr | 9); + free_ptr += 512 * sizeof(unsigned long); + } + ptep = read_pgd(i); + store_pte(&ptep[j], 0xc000000000000000 | ((unsigned long)pa & + 0x00fffffffffff000) | perm_attr); + eas_mapped[neas_mapped++] = ea; +} + +void unmap(void *ea) +{ + unsigned long epn = (unsigned long) ea >> 12; + unsigned long i, j; + unsigned long *ptep; + + i = (epn >> 9) & 0x3ff; + j = epn & 0x1ff; + if (pgdir[i] == 0) { + return; + } + ptep = read_pgd(i); + store_pte(&ptep[j], 0); + tlbie_va((unsigned long)ea, PRS); +} + +void unmap_all(void) +{ + int i; + + for (i = 0; i < neas_mapped; ++i) { + unmap(eas_mapped[i]); + } + neas_mapped = 0; +} + +int mmu_test_1(void) +{ + long *ptr = (long *) 0x123000; + long val; + + /* this should fail */ + if (test_read(ptr, &val, 0xdeadbeefd00d)) { + return 1; + } + /* dest reg of load should be unchanged */ + if (val != 0xdeadbeefd00d) { + return 2; + } + /* DAR and DSISR should be set correctly */ + if (mfspr(DAR) != (long) ptr || mfspr(DSISR) != 0x40000000) { + return 3; + } + return 0; +} + +int mmu_test_2(void) +{ + long *mem = (long *) 0x8000; + long *ptr = (long *) 0x124000; + long *ptr2 = (long *) 0x1124000; + long val; + + /* create PTE */ + map(ptr, mem, DFLT_PERM); + /* initialize the memory content */ + mem[33] = 0xbadc0ffee; + /* this should succeed and be a cache miss */ + if (!test_read(&ptr[33], &val, 0xdeadbeefd00d)) { + return 1; + } + /* dest reg of load should have the value written */ + if (val != 0xbadc0ffee) { + return 2; + } + /* load a second TLB entry in the same set as the first */ + map(ptr2, mem, DFLT_PERM); + /* this should succeed and be a cache hit */ + if (!test_read(&ptr2[33], &val, 0xdeadbeefd00d)) { + return 3; + } + /* dest reg of load should have the value written */ + if (val != 0xbadc0ffee) { + return 4; + } + /* check that the first entry still works */ + if (!test_read(&ptr[33], &val, 0xdeadbeefd00d)) { + return 5; + } + if (val != 0xbadc0ffee) { + return 6; + } + return 0; +} + +int mmu_test_3(void) +{ + long *mem = (long *) 0x9000; + long *ptr = (long *) 0x14a000; + long val; + + /* create PTE */ + map(ptr, mem, DFLT_PERM); + /* initialize the memory content */ + mem[45] = 0xfee1800d4ea; + /* this should succeed and be a cache miss */ + if (!test_read(&ptr[45], &val, 0xdeadbeefd0d0)) { + return 1; + } + /* dest reg of load should have the value written */ + if (val != 0xfee1800d4ea) { + return 2; + } + /* remove the PTE */ + unmap(ptr); + /* this should fail */ + if (test_read(&ptr[45], &val, 0xdeadbeefd0d0)) { + return 3; + } + /* dest reg of load should be unchanged */ + if (val != 0xdeadbeefd0d0) { + return 4; + } + /* DAR and DSISR should be set correctly */ + if (mfspr(DAR) != (long) &ptr[45] || mfspr(DSISR) != 0x40000000) { + return 5; + } + return 0; +} + +int mmu_test_4(void) +{ + long *mem = (long *) 0xa000; + long *ptr = (long *) 0x10b000; + long *ptr2 = (long *) 0x110b000; + long val; + + /* create PTE */ + map(ptr, mem, DFLT_PERM); + /* initialize the memory content */ + mem[27] = 0xf00f00f00f00; + /* this should succeed and be a cache miss */ + if (!test_write(&ptr[27], 0xe44badc0ffee)) { + return 1; + } + /* memory should now have the value written */ + if (mem[27] != 0xe44badc0ffee) { + return 2; + } + /* load a second TLB entry in the same set as the first */ + map(ptr2, mem, DFLT_PERM); + /* this should succeed and be a cache hit */ + if (!test_write(&ptr2[27], 0x6e11ae)) { + return 3; + } + /* memory should have the value written */ + if (mem[27] != 0x6e11ae) { + return 4; + } + /* check that the first entry still exists */ + /* (assumes TLB is 2-way associative or more) */ + if (!test_read(&ptr[27], &val, 0xdeadbeefd00d)) { + return 5; + } + if (val != 0x6e11ae) { + return 6; + } + return 0; +} + +int mmu_test_5(void) +{ + long *mem = (long *) 0xbffd; + long *ptr = (long *) 0x39fffd; + long val; + + /* create PTE */ + map(ptr, mem, DFLT_PERM); + /* this should fail */ + if (test_read(ptr, &val, 0xdeadbeef0dd0)) { + return 1; + } + /* dest reg of load should be unchanged */ + if (val != 0xdeadbeef0dd0) { + return 2; + } + /* DAR and DSISR should be set correctly */ + if (mfspr(DAR) != ((long)ptr & ~0xfff) + 0x1000 || + mfspr(DSISR) != 0x40000000) { + return 3; + } + return 0; +} + +int mmu_test_6(void) +{ + long *mem = (long *) 0xbffd; + long *ptr = (long *) 0x39fffd; + + /* create PTE */ + map(ptr, mem, DFLT_PERM); + /* initialize memory */ + *mem = 0x123456789abcdef0; + /* this should fail */ + if (test_write(ptr, 0xdeadbeef0dd0)) { + return 1; + } + /* DAR and DSISR should be set correctly */ + if (mfspr(DAR) != ((long)ptr & ~0xfff) + 0x1000 || + mfspr(DSISR) != 0x42000000) { + return 2; + } + return 0; +} + +int mmu_test_7(void) +{ + long *mem = (long *) 0x8000; + long *ptr = (long *) 0x124000; + long val; + + *mem = 0x123456789abcdef0; + /* create PTE without read or write permission */ + map(ptr, mem, REF); + /* this should fail */ + if (test_read(ptr, &val, 0xdeadd00dbeef)) { + return 1; + } + /* dest reg of load should be unchanged */ + if (val != 0xdeadd00dbeef) { + return 2; + } + /* DAR and DSISR should be set correctly */ + if (mfspr(DAR) != (long) ptr || mfspr(DSISR) != 0x08000000) { + return 3; + } + /* this should fail */ + if (test_write(ptr, 0xdeadbeef0dd1)) { + return 4; + } + /* DAR and DSISR should be set correctly */ + if (mfspr(DAR) != (long)ptr || mfspr(DSISR) != 0x0a000000) { + return 5; + } + /* memory should be unchanged */ + if (*mem != 0x123456789abcdef0) { + return 6; + } + return 0; +} + +int mmu_test_8(void) +{ + long *mem = (long *) 0x8000; + long *ptr = (long *) 0x124000; + long val; + + *mem = 0x123456789abcdef0; + /* create PTE with read but not write permission */ + map(ptr, mem, REF | PERM_RD); + /* this should succeed */ + if (!test_read(ptr, &val, 0xdeadd00dbeef)) { + return 1; + } + /* this should fail */ + if (test_write(ptr, 0xdeadbeef0dd1)) { + return 2; + } + /* DAR and DSISR should be set correctly */ + if (mfspr(DAR) != (long)ptr || mfspr(DSISR) != 0x0a000000) { + return 3; + } + /* memory should be unchanged */ + if (*mem != 0x123456789abcdef0) { + return 4; + } + return 0; +} + +int mmu_test_9(void) +{ + unsigned long ptr = 0x523000; + + /* this should fail */ + if (test_exec(0, ptr, MSR_DFLT | MSR_IR)) { + return 1; + } + /* SRR0 and SRR1 should be set correctly */ + if (mfspr(SRR0) != (long) ptr || + mfspr(SRR1) != (MSR_DFLT | 0x40000000 | MSR_IR)) { + return 2; + } + return 0; +} + +int mmu_test_10(void) +{ + unsigned long mem = 0x1000; + unsigned long ptr = 0x324000; + unsigned long ptr2 = 0x1324000; + + /* create PTE */ + map((void *)ptr, (void *)mem, PERM_EX | REF); + /* this should succeed and be a cache miss */ + if (!test_exec(0, ptr, MSR_DFLT | MSR_IR)) { + return 1; + } + /* create a second PTE */ + map((void *)ptr2, (void *)mem, PERM_EX | REF); + /* this should succeed and be a cache hit */ + if (!test_exec(0, ptr2, MSR_DFLT | MSR_IR)) { + return 2; + } + return 0; +} + +int mmu_test_11(void) +{ + unsigned long mem = 0x1000; + unsigned long ptr = 0x349000; + unsigned long ptr2 = 0x34a000; + + /* create a PTE */ + map((void *)ptr, (void *)mem, PERM_EX | REF); + /* this should succeed */ + if (!test_exec(1, ptr, MSR_DFLT | MSR_IR)) { + return 1; + } + /* invalidate the PTE */ + unmap((void *)ptr); + /* install a second PTE */ + map((void *)ptr2, (void *)mem, PERM_EX | REF); + /* this should fail */ + if (test_exec(1, ptr, MSR_DFLT | MSR_IR)) { + return 2; + } + /* SRR0 and SRR1 should be set correctly */ + if (mfspr(SRR0) != (long) ptr || + mfspr(SRR1) != (MSR_DFLT | 0x40000000 | MSR_IR)) { + return 3; + } + return 0; +} + +int mmu_test_12(void) +{ + unsigned long mem = 0x1000; + unsigned long mem2 = 0x2000; + unsigned long ptr = 0x30a000; + unsigned long ptr2 = 0x30b000; + + /* create a PTE */ + map((void *)ptr, (void *)mem, PERM_EX | REF); + /* this should fail due to second page not being mapped */ + if (test_exec(2, ptr, MSR_DFLT | MSR_IR)) { + return 1; + } + /* SRR0 and SRR1 should be set correctly */ + if (mfspr(SRR0) != ptr2 || + mfspr(SRR1) != (MSR_DFLT | 0x40000000 | MSR_IR)) { + return 2; + } + /* create a PTE for the second page */ + map((void *)ptr2, (void *)mem2, PERM_EX | REF); + /* this should succeed */ + if (!test_exec(2, ptr, MSR_DFLT | MSR_IR)) { + return 3; + } + return 0; +} + +int mmu_test_13(void) +{ + unsigned long mem = 0x1000; + unsigned long ptr = 0x324000; + + /* create a PTE without execute permission */ + map((void *)ptr, (void *)mem, DFLT_PERM); + /* this should fail */ + if (test_exec(0, ptr, MSR_DFLT | MSR_IR)) { + return 1; + } + /* SRR0 and SRR1 should be set correctly */ + if (mfspr(SRR0) != ptr || + mfspr(SRR1) != (MSR_DFLT | 0x10000000 | MSR_IR)) { + return 2; + } + return 0; +} + +int mmu_test_14(void) +{ + unsigned long mem = 0x1000; + unsigned long mem2 = 0x2000; + unsigned long ptr = 0x30a000; + unsigned long ptr2 = 0x30b000; + + /* create a PTE */ + map((void *)ptr, (void *)mem, PERM_EX | REF); + /* create a PTE for the second page without execute permission */ + map((void *)ptr2, (void *)mem2, PERM_RD | REF); + /* this should fail due to second page being no-execute */ + if (test_exec(2, ptr, MSR_DFLT | MSR_IR)) { + return 1; + } + /* SRR0 and SRR1 should be set correctly */ + if (mfspr(SRR0) != ptr2 || + mfspr(SRR1) != (MSR_DFLT | 0x10000000 | MSR_IR)) { + return 2; + } + /* create a PTE for the second page with execute permission */ + map((void *)ptr2, (void *)mem2, PERM_RD | PERM_EX | REF); + /* this should succeed */ + if (!test_exec(2, ptr, MSR_DFLT | MSR_IR)) { + return 3; + } + return 0; +} + +int mmu_test_15(void) +{ + unsigned long mem = 0x1000; + unsigned long ptr = 0x349000; + + /* create a PTE without ref or execute permission */ + map((void *)ptr, (void *)mem, 0); + /* this should fail */ + if (test_exec(2, ptr, MSR_DFLT | MSR_IR)) { + return 1; + } + /* SRR0 and SRR1 should be set correctly */ + /* RC update fail bit should not be set */ + if (mfspr(SRR0) != (long) ptr || + mfspr(SRR1) != (MSR_DFLT | 0x10000000 | MSR_IR)) { + return 2; + } + return 0; +} + +int mmu_test_16(void) +{ + long *mem = (long *) 0x8000; + long *ptr = (long *) 0x124000; + long *ptr2 = (long *) 0x1124000; + + /* create PTE */ + map(ptr, mem, DFLT_PERM); + /* this should succeed and be a cache miss */ + if (!test_dcbz(&ptr[129])) { + return 1; + } + /* create a second PTE */ + map(ptr2, mem, DFLT_PERM); + /* this should succeed and be a cache hit */ + if (!test_dcbz(&ptr2[130])) { + return 2; + } + return 0; +} + +int mmu_test_17(void) +{ + long *mem = (long *) 0x8000; + long *ptr = (long *) 0x124000; + + *mem = 0x123456789abcdef0; + /* create PTE with read but not write permission */ + map(ptr, mem, REF | PERM_RD); + /* this should fail and create a TLB entry */ + if (test_write(ptr, 0xdeadbeef0dd1)) { + return 1; + } + /* DAR and DSISR should be set correctly */ + if (mfspr(DAR) != (long)ptr || mfspr(DSISR) != 0x0a000000) { + return 2; + } + /* Update the PTE to have write permission */ + map(ptr, mem, REF | CHG | PERM_RD | PERM_WR); + /* this should succeed */ + if (!test_write(ptr, 0xdeadbeef0dd1)) { + return 3; + } + return 0; +} + +int fail; + +void do_test(int num, int (*test)(void)) +{ + int ret; + + mtspr(DSISR, 0); + mtspr(DAR, 0); + unmap_all(); + ml_printf("test %d:", num); + ret = test(); + if (ret == 0) { + ml_printf("PASS\r\n"); + } else { + fail = 1; + ml_printf("FAIL %d", ret); + if (num <= 10 || num == 19) { + ml_printf(" DAR=%lx DSISR=%lx", mfspr(DAR), mfspr(DSISR)); + } else { + ml_printf(" SRR0=%lx SRR1=%lx", mfspr(SRR0), mfspr(SRR1)); + } + ml_printf("\r\n"); + } +} + +int main(void) +{ + init_mmu(); + + do_test(1, mmu_test_1); + do_test(2, mmu_test_2); + do_test(3, mmu_test_3); + do_test(4, mmu_test_4); + do_test(5, mmu_test_5); + do_test(6, mmu_test_6); + do_test(7, mmu_test_7); + do_test(8, mmu_test_8); + do_test(9, mmu_test_9); + do_test(10, mmu_test_10); + do_test(11, mmu_test_11); + do_test(12, mmu_test_12); + do_test(13, mmu_test_13); + do_test(14, mmu_test_14); + do_test(15, mmu_test_15); + do_test(16, mmu_test_16); + do_test(17, mmu_test_17); + + return fail; +} diff --git a/tests/tcg/ppc64/system/mmu.h b/tests/tcg/ppc64/system/mmu.h new file mode 100644 index 0000000000..eb191e4bd0 --- /dev/null +++ b/tests/tcg/ppc64/system/mmu.h @@ -0,0 +1,9 @@ +#ifndef PPC64_MMU_H +#define PPC64_MMU_H + +int test_read(long *addr, long *ret, long init); +int test_write(long *addr, long val); +int test_dcbz(long *addr); +int test_exec(int testno, unsigned long pc, unsigned long msr); + +#endif From patchwork Thu Mar 31 14:58:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leandro Lupori X-Patchwork-Id: 1611834 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) 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 bilbo.ozlabs.org (Postfix) with ESMTPS id 4KTnZZ4HJKz9sGG for ; Fri, 1 Apr 2022 02:40:54 +1100 (AEDT) Received: from localhost ([::1]:41080 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nZwuq-0004q4-HH for incoming@patchwork.ozlabs.org; Thu, 31 Mar 2022 11:40:52 -0400 Received: from eggs.gnu.org ([209.51.188.92]:56232) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nZwfX-0003SV-9X; Thu, 31 Mar 2022 11:25:03 -0400 Received: from [187.72.171.209] (port=51585 helo=outlook.eldorado.org.br) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nZwfR-0004ne-Go; Thu, 31 Mar 2022 11:25:02 -0400 Received: from p9ibm ([10.10.71.235]) by outlook.eldorado.org.br over TLS secured channel with Microsoft SMTPSVC(8.5.9600.16384); Thu, 31 Mar 2022 12:24:02 -0300 Received: from eldorado.org.br (unknown [10.10.70.45]) by p9ibm (Postfix) with ESMTP id 3ACE88014EA; Thu, 31 Mar 2022 11:58:44 -0300 (-03) From: Leandro Lupori To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Subject: [RFC PATCH v2 5/5] tests/tcg/ppc64: build PowerNV and LE tests Date: Thu, 31 Mar 2022 11:58:13 -0300 Message-Id: <20220331145813.21719-6-leandro.lupori@eldorado.org.br> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220331145813.21719-1-leandro.lupori@eldorado.org.br> References: <20220331145813.21719-1-leandro.lupori@eldorado.org.br> MIME-Version: 1.0 X-OriginalArrivalTime: 31 Mar 2022 15:24:02.0484 (UTC) FILETIME=[5A0BAF40:01D84513] X-Host-Lookup-Failed: Reverse DNS lookup failed for 187.72.171.209 (failed) Received-SPF: pass client-ip=187.72.171.209; envelope-from=leandro.lupori@eldorado.org.br; helo=outlook.eldorado.org.br X-Spam_score_int: -4 X-Spam_score: -0.5 X-Spam_bar: / X-Spam_report: (-0.5 / 5.0 requ) BAYES_00=-1.9, PDS_HP_HELO_NORDNS=0.659, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01, UPPERCASE_50_75=0.008 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Leandro Lupori , danielhb413@gmail.com, richard.henderson@linaro.org, groug@kaod.org, clg@kaod.org, pbonzini@redhat.com, alex.bennee@linaro.org, david@gibson.dropbear.id.au Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Each Microwatt/PowerNV test use its own head.S file and thus needs different build rules. Also add rules to build and run all tests in LE mode. Signed-off-by: Leandro Lupori --- tests/tcg/ppc64/Makefile.softmmu-rules | 34 +++++++ tests/tcg/ppc64/Makefile.softmmu-target | 119 ++++++++++++++++++------ 2 files changed, 126 insertions(+), 27 deletions(-) create mode 100644 tests/tcg/ppc64/Makefile.softmmu-rules diff --git a/tests/tcg/ppc64/Makefile.softmmu-rules b/tests/tcg/ppc64/Makefile.softmmu-rules new file mode 100644 index 0000000000..abe0de0a7f --- /dev/null +++ b/tests/tcg/ppc64/Makefile.softmmu-rules @@ -0,0 +1,34 @@ +# +# Rules to build PowerPC64 softmmu tests, for both BE and LE +# + +# Build CRT and test objects +%$(LE_SUFFIX).o: $(CRT_PATH)/%.S + $(CC) $(PPC64_CFLAGS) -x assembler-with-cpp -c $< -o $@ + +%$(LE_SUFFIX).o: %.S + $(CC) $(PPC64_CFLAGS) -x assembler-with-cpp -c $< -o $@ + +%$(LE_SUFFIX).o: $(CRT_PATH)/%.c + $(CC) $(PPC64_CFLAGS) -c $< -o $@ + +%$(LE_SUFFIX).o: %.c + $(CC) $(PPC64_CFLAGS) -c $< -o $@ + +# Build .elf files for debugging +%$(LE_SUFFIX).elf: %$(LE_SUFFIX).o $(LINK_SCRIPT) $(CRT_DEPS) $(MINILIB_DEPS) + $(CC) $(PPC64_CFLAGS) -o $@ $< $(LDFLAGS) + +$(PPC64_PNV_ELFS): %$(LE_SUFFIX).elf: %-head$(LE_SUFFIX).o %$(LE_SUFFIX).o \ + $(LINK_SCRIPT) $(CRT_DEPS) $(MINILIB_DEPS) + $(CC) $(PPC64_CFLAGS) -o $@ $< $*$(LE_SUFFIX).o $(LDFLAGS) + +# Build test binaries +%$(LE_SUFFIX): %$(LE_SUFFIX).o $(LINK_SCRIPT) $(CRT_DEPS) $(MINILIB_DEPS) \ + %$(LE_SUFFIX).elf + $(CC) $(PPC64_CFLAGS) -o $@ $< $(LDFLAGS) -Wl,--oformat=binary + +$(PPC64_PNV_TESTS): %$(LE_SUFFIX): %-head$(LE_SUFFIX).o %$(LE_SUFFIX).o \ + $(LINK_SCRIPT) $(CRT_DEPS) $(MINILIB_DEPS) %$(LE_SUFFIX).elf + $(CC) $(PPC64_CFLAGS) -o $@ $< $*$(LE_SUFFIX).o $(LDFLAGS) \ + -Wl,--oformat=binary diff --git a/tests/tcg/ppc64/Makefile.softmmu-target b/tests/tcg/ppc64/Makefile.softmmu-target index 8f9925ca5a..03d5d3e426 100644 --- a/tests/tcg/ppc64/Makefile.softmmu-target +++ b/tests/tcg/ppc64/Makefile.softmmu-target @@ -5,25 +5,52 @@ # For now, disable tests that are failing DISABLED_TESTS := memory DISABLED_EXTRA_RUNS := run-gdbstub-memory +# Disable LE tests too +DISABLED_TESTS += $(addsuffix -le, $(DISABLED_TESTS)) +DISABLED_EXTRA_RUNS += $(addsuffix -le, $(DISABLED_EXTRA_RUNS)) -PPC64_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/ppc64/system -VPATH+=$(PPC64_SYSTEM_SRC) +PPC64_SRC := $(SRC_PATH)/tests/tcg/ppc64 +PPC64_SYSTEM_SRC := $(PPC64_SRC)/system +VPATH += $(PPC64_SYSTEM_SRC) # These objects provide the basic boot code and helper functions for all tests -CRT_PATH=$(PPC64_SYSTEM_SRC)/lib -CRT_OBJS=boot.o console.o +CRT_PATH := $(PPC64_SYSTEM_SRC)/lib +CRT_OBJS_BE := boot.o console.o +CRT_OBJS_LE := $(patsubst %.o, %-le.o, $(CRT_OBJS_BE)) +# NOTE: %-head.o replaces boot.o on PowerNV tests +PNV_CRT_OBJS_BE := $(filter-out boot.o, $(CRT_OBJS_BE)) +PNV_CRT_OBJS_LE := $(filter-out boot-le.o, $(CRT_OBJS_LE)) -PPC64_TEST_SRCS=$(wildcard $(PPC64_SYSTEM_SRC)/*.c) -PPC64_TESTS=$(patsubst $(PPC64_SYSTEM_SRC)/%.c, %, $(PPC64_TEST_SRCS)) +MINILIB_OBJS_BE := $(MINILIB_OBJS) +MINILIB_OBJS_LE := $(patsubst %.o, %-le.o, $(MINILIB_OBJS)) -LINK_SCRIPT=$(CRT_PATH)/powerpc.lds -# NOTE: --build-id is stored before the first code section in the linked -# binary, which causes problems for most tests, that expect to -# begin at address 0. -LDFLAGS=-Wl,-T$(LINK_SCRIPT) -Wl,--build-id=none -static -nostdlib \ - $(CRT_OBJS) $(MINILIB_OBJS) -lgcc -TESTS += $(filter-out $(DISABLED_TESTS),$(PPC64_TESTS) $(MULTIARCH_TESTS)) -EXTRA_RUNS += $(filter-out $(DISABLED_EXTRA_RUNS),$(MULTIARCH_RUNS)) +# Add BE and LE tests + +# Each Microwatt/PowerNV test use its own head.S file and thus needs +# different rules. +PPC64BE_PNV_TESTS := mmu +PPC64BE_PNV_ELFS := $(addsuffix .elf, $(PPC64BE_PNV_TESTS)) +PPC64LE_PNV_TESTS := $(addsuffix -le, $(PPC64BE_PNV_TESTS)) +PPC64LE_PNV_ELFS := $(addsuffix .elf, $(PPC64LE_PNV_TESTS)) + +# Remaining test sources are assumed to be non-PowerNV tests +PPC64_TEST_SRCS := $(wildcard $(PPC64_SYSTEM_SRC)/*.c) +PPC64BE_TESTS := $(MULTIARCH_TESTS) +PPC64BE_TESTS += $(filter-out $(PPC64BE_PNV_TESTS),\ + $(patsubst $(PPC64_SYSTEM_SRC)/%.c, %, $(PPC64_TEST_SRCS))) +PPC64BE_ELFS := $(addsuffix .elf,$(PPC64BE_TESTS)) +PPC64LE_TESTS := $(addsuffix -le, $(PPC64BE_TESTS)) +PPC64LE_ELFS := $(addsuffix .elf,$(PPC64LE_TESTS)) + +TESTS += $(filter-out $(DISABLED_TESTS), $(PPC64BE_TESTS) $(PPC64LE_TESTS)) +TESTS += $(PPC64BE_PNV_TESTS) $(PPC64LE_PNV_TESTS) + +MULTIARCH_RUNS_BE := $(MULTIARCH_RUNS) +MULTIARCH_RUNS_LE := $(addsuffix -le, $(MULTIARCH_RUNS)) +EXTRA_RUNS += $(filter-out $(DISABLED_EXTRA_RUNS), \ + $(MULTIARCH_RUNS_BE) $(MULTIARCH_RUNS_LE)) + +LINK_SCRIPT := $(CRT_PATH)/powerpc.lds # NOTE: -Os doesn't work well with -Wl,--oformat=binary # Some linker generated functions, such as savegpr*/restgpr*, @@ -33,26 +60,64 @@ CFLAGS = -O -g -Wall -std=c99 -msoft-float -mno-vsx -mno-altivec \ -I $(PPC64_SYSTEM_SRC)/include $(MINILIB_INC) \ -mcpu=power8 +# NOTE: --build-id is stored before the first code section in the linked +# binary, which causes problems for most tests, that expect to +# begin at address 0. +LDFLAGS = -Wl,-T$(LINK_SCRIPT) -Wl,--build-id=none -static -nostdlib \ + $(CRT_OBJS) $(MINILIB_OBJS) -lgcc + +memory memory-le: CFLAGS+=-DCHECK_UNALIGNED=1 + +# PowerNV tests build outputs +PPC64BE_PNV_OUTPUTS := $(PPC64BE_PNV_TESTS) $(PPC64BE_PNV_ELFS) +PPC64LE_PNV_OUTPUTS := $(PPC64LE_PNV_TESTS) $(PPC64LE_PNV_ELFS) +# Non-PowerNV tests build outputs +PPC64BE_OUTPUTS := $(PPC64BE_TESTS) $(PPC64BE_ELFS) +PPC64LE_OUTPUTS := $(PPC64LE_TESTS) $(PPC64LE_ELFS) +# Outputs of all tests +PPC64BE_ALL_OUTPUTS := $(PPC64BE_OUTPUTS) $(PPC64BE_PNV_OUTPUTS) +PPC64LE_ALL_OUTPUTS := $(PPC64LE_OUTPUTS) $(PPC64LE_PNV_OUTPUTS) + +PPC64_CFLAGS = $(CFLAGS) $(EXTRA_CFLAGS) $(PPC64LE_CFLAGS) + # Leave the .elf files, to make debugging easier -.PRECIOUS: $(CRT_OBJS) $(addsuffix .elf,$(TESTS)) +.PRECIOUS: $(CRT_OBJS_BE) $(CRT_OBJS_LE) $(addsuffix .elf,$(TESTS)) + +# BE rules + +LE_SUFFIX := +CRT_DEPS := $(CRT_OBJS_BE) +MINILIB_DEPS := $(MINILIB_OBJS_BE) +PPC64_PNV_ELFS := $(PPC64BE_PNV_ELFS) +PPC64_PNV_TESTS := $(PPC64BE_PNV_TESTS) + +$(PPC64BE_ALL_OUTPUTS): LE_SUFFIX = +$(PPC64BE_ALL_OUTPUTS): PPC64LE_CFLAGS = +$(PPC64BE_OUTPUTS): CRT_OBJS = $(CRT_OBJS_BE) +$(PPC64BE_PNV_OUTPUTS): CRT_OBJS = $(PNV_CRT_OBJS_BE) +$(PPC64BE_ALL_OUTPUTS): MINILIB_OBJS = $(MINILIB_OBJS_BE) -# Build CRT objects -%.o: $(CRT_PATH)/%.S - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@ +include $(PPC64_SRC)/Makefile.softmmu-rules -%.o: $(CRT_PATH)/%.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@ +# LE rules -# Build and link the tests +LE_SUFFIX := -le +CRT_DEPS := $(CRT_OBJS_LE) +MINILIB_DEPS := $(MINILIB_OBJS_LE) +PPC64_PNV_ELFS := $(PPC64LE_PNV_ELFS) +PPC64_PNV_TESTS := $(PPC64LE_PNV_TESTS) -# The .elf files are just for debugging -%.elf: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS) - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) +$(PPC64LE_ALL_OUTPUTS): LE_SUFFIX = -le +$(PPC64LE_ALL_OUTPUTS): PPC64LE_CFLAGS = -mlittle-endian -mabi=elfv2 +$(PPC64LE_OUTPUTS): CRT_OBJS = $(CRT_OBJS_LE) +$(PPC64LE_PNV_OUTPUTS): CRT_OBJS = $(PNV_CRT_OBJS_LE) +$(PPC64LE_ALL_OUTPUTS): MINILIB_OBJS = $(MINILIB_OBJS_LE) -%: %.c %.elf $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS) - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) -Wl,--oformat=binary +include $(PPC64_SRC)/Makefile.softmmu-rules -memory: CFLAGS+=-DCHECK_UNALIGNED=1 +# Build LE Minilib objs +%-le.o: $(SYSTEM_MINILIB_SRC)/%.c + $(CC) $(PPC64_CFLAGS) -c $< -o $@ # Running QEMU_BASE_MACHINE=-cpu power9 -M powernv9 -m 1G -vga none -nographic