From patchwork Fri Jul 9 05:16:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366707 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.8 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 02D81C07E9B for ; Fri, 9 Jul 2021 05:19:35 +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 6E27561363 for ; Fri, 9 Jul 2021 05:19:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6E27561363 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:41460 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1ivG-0003vz-8Z for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:19:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35050) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itZ-0000rm-IK; Fri, 09 Jul 2021 01:17:49 -0400 Received: from ozlabs.org ([203.11.71.1]:44035) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itV-0001pJ-KH; Fri, 09 Jul 2021 01:17:49 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd0tGnz9sWq; Fri, 9 Jul 2021 15:17:32 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=NgKKvWQQ4LgL+Vxg0v2t69b+p8LZ8h4r1BzGx9jw3sY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S72yEXZgkCKohVBBBT1brp1UW20iGVlbG4ORaSdghJ1K6G64AqjS5f5LzpjGOF0X9 HouSdMhuuHc6cMOrYtlxRc4pwEN/jHF4Xz+63EVkIXdRbbAJQ8IXjy0qDXh4evL2TO 2f7X0vWVcO72S7DZRl9RXZSrysuZPPQQIExPzrFE= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 01/33] target/ppc: Introduce ppc_interrupts_little_endian() Date: Fri, 9 Jul 2021 15:16:56 +1000 Message-Id: <20210709051728.170203-2-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, Fabiano Rosas Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Greg Kurz PowerPC CPUs use big endian by default but starting with POWER7, server grade CPUs use the ILE bit of the LPCR special purpose register to decide on the endianness to use when handling interrupts. This gives a clue to QEMU on the endianness the guest kernel is running, which is needed when generating an ELF dump of the guest or when delivering an FWNMI machine check interrupt. Commit 382d2db62bcb ("target-ppc: Introduce callback for interrupt endianness") added a class method to PowerPCCPUClass to modelize this : default implementation returns a fixed "big endian" value, while POWER7 and newer do the LPCR_ILE check. This is suboptimal as it forces to implement the method for every new CPU family, and it is very unlikely that this will ever be different than what we have today. We basically only have three cases to consider: a) CPU doesn't have an LPCR => big endian b) CPU has an LPCR but doesn't support the ILE bit => big endian c) CPU has an LPCR and supports the ILE bit => little or big endian Instead of class methods, introduce an inline helper that checks the ILE bit in the LPCR_MASK to decide on the outcome. The new helper words little endian instead of big endian. This allows to drop a ! operator in ppc_cpu_do_fwnmi_machine_check(). Signed-off-by: Greg Kurz Message-Id: <20210622140926.677618-2-groug@kaod.org> Reviewed-by: Fabiano Rosas Signed-off-by: David Gibson --- target/ppc/arch_dump.c | 8 +++----- target/ppc/cpu.h | 15 +++++++++++++++ target/ppc/excp_helper.c | 3 +-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c index 9210e61ef4..bb392f6d88 100644 --- a/target/ppc/arch_dump.c +++ b/target/ppc/arch_dump.c @@ -227,22 +227,20 @@ int cpu_get_dump_info(ArchDumpInfo *info, const struct GuestPhysBlockList *guest_phys_blocks) { PowerPCCPU *cpu; - PowerPCCPUClass *pcc; if (first_cpu == NULL) { return -1; } cpu = POWERPC_CPU(first_cpu); - pcc = POWERPC_CPU_GET_CLASS(cpu); info->d_machine = PPC_ELF_MACHINE; info->d_class = ELFCLASS; - if ((*pcc->interrupts_big_endian)(cpu)) { - info->d_endian = ELFDATA2MSB; - } else { + if (ppc_interrupts_little_endian(cpu)) { info->d_endian = ELFDATA2LSB; + } else { + info->d_endian = ELFDATA2MSB; } /* 64KB is the max page size for pseries kernel */ if (strncmp(object_get_typename(qdev_get_machine()), diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index b4de0db7ff..93d308ac8f 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -2643,6 +2643,21 @@ static inline bool ppc_has_spr(PowerPCCPU *cpu, int spr) return cpu->env.spr_cb[spr].name != NULL; } +static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu) +{ + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); + + /* + * Only models that have an LPCR and know about LPCR_ILE can do little + * endian. + */ + if (pcc->lpcr_mask & LPCR_ILE) { + return !!(cpu->env.spr[SPR_LPCR] & LPCR_ILE); + } + + return false; +} + void dump_mmu(CPUPPCState *env); void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len); diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index fd147e2a37..a79a0ed465 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1099,7 +1099,6 @@ void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector) { PowerPCCPU *cpu = POWERPC_CPU(cs); CPUPPCState *env = &cpu->env; - PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); target_ulong msr = 0; /* @@ -1108,7 +1107,7 @@ void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector) */ msr = (1ULL << MSR_ME); msr |= env->msr & (1ULL << MSR_SF); - if (!(*pcc->interrupts_big_endian)(cpu)) { + if (ppc_interrupts_little_endian(cpu)) { msr |= (1ULL << MSR_LE); } From patchwork Fri Jul 9 05:16:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366709 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.8 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 3642CC07E9C for ; Fri, 9 Jul 2021 05:19:36 +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 ACBC36140F for ; Fri, 9 Jul 2021 05:19:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org ACBC36140F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:41462 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1ivG-0003wF-TQ for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:19:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35022) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itY-0000rO-4b; Fri, 09 Jul 2021 01:17:48 -0400 Received: from bilbo.ozlabs.org ([2401:3900:2:1::2]:54881 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itV-0001pG-HF; Fri, 09 Jul 2021 01:17:47 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHc6kZcz9sWS; Fri, 9 Jul 2021 15:17:32 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807852; bh=gXUuEtCR4TYTn8HM+OXKsTlWBnv4uXGKfvHWjycKEmM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Bj2Fx91Tws2Ih2gf819nhQp6jCkv+FOaJNnGiTh6CYvvsWbSGFCxpa1TNBYG1m5bC iEs8lmgR0PcYTPrqFzhv9bYjsR1dyG4512byo02tYs8Y+7J0SD38mekM8vNc4yIrbv deYqbHOIrOn4m6A+eflnWDiHvrRxUW4PtqksjmoM= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 02/33] target/ppc: Drop PowerPCCPUClass::interrupts_big_endian() Date: Fri, 9 Jul 2021 15:16:57 +1000 Message-Id: <20210709051728.170203-3-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, Fabiano Rosas Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Greg Kurz This isn't used anymore. Signed-off-by: Greg Kurz Message-Id: <20210622140926.677618-3-groug@kaod.org> Reviewed-by: Fabiano Rosas Signed-off-by: David Gibson --- target/ppc/cpu-qom.h | 1 - target/ppc/cpu_init.c | 17 ----------------- 2 files changed, 18 deletions(-) diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h index 06b6571bc9..7b424e3cb0 100644 --- a/target/ppc/cpu-qom.h +++ b/target/ppc/cpu-qom.h @@ -199,7 +199,6 @@ struct PowerPCCPUClass { void (*init_proc)(CPUPPCState *env); int (*check_pow)(CPUPPCState *env); int (*handle_mmu_fault)(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx); - bool (*interrupts_big_endian)(PowerPCCPU *cpu); }; #ifndef CONFIG_USER_ONLY diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index d0411e7302..1a22aef874 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -2666,18 +2666,6 @@ static int check_pow_hid0_74xx(CPUPPCState *env) return 0; } -static bool ppc_cpu_interrupts_big_endian_always(PowerPCCPU *cpu) -{ - return true; -} - -#ifdef TARGET_PPC64 -static bool ppc_cpu_interrupts_big_endian_lpcr(PowerPCCPU *cpu) -{ - return !(cpu->env.spr[SPR_LPCR] & LPCR_ILE); -} -#endif - /*****************************************************************************/ /* PowerPC implementations definitions */ @@ -7740,7 +7728,6 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) POWERPC_FLAG_VSX; pcc->l1_dcache_size = 0x8000; pcc->l1_icache_size = 0x8000; - pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr; } static void init_proc_POWER8(CPUPPCState *env) @@ -7918,7 +7905,6 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data) POWERPC_FLAG_VSX | POWERPC_FLAG_TM; pcc->l1_dcache_size = 0x8000; pcc->l1_icache_size = 0x8000; - pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr; } #ifdef CONFIG_SOFTMMU @@ -8136,7 +8122,6 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) POWERPC_FLAG_VSX | POWERPC_FLAG_TM | POWERPC_FLAG_SCV; pcc->l1_dcache_size = 0x8000; pcc->l1_icache_size = 0x8000; - pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr; } #ifdef CONFIG_SOFTMMU @@ -8347,7 +8332,6 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data) POWERPC_FLAG_VSX | POWERPC_FLAG_TM | POWERPC_FLAG_SCV; pcc->l1_dcache_size = 0x8000; pcc->l1_icache_size = 0x8000; - pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr; } #if !defined(CONFIG_USER_ONLY) @@ -9094,7 +9078,6 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) device_class_set_parent_unrealize(dc, ppc_cpu_unrealize, &pcc->parent_unrealize); pcc->pvr_match = ppc_pvr_match_default; - pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always; device_class_set_props(dc, ppc_cpu_properties); device_class_set_parent_reset(dc, ppc_cpu_reset, &pcc->parent_reset); From patchwork Fri Jul 9 05:16:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366713 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=-15.1 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,URIBL_BLACK,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 60379C07E99 for ; Fri, 9 Jul 2021 05:22:39 +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 1A4BF61363 for ; Fri, 9 Jul 2021 05:22:39 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1A4BF61363 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:50124 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1iyE-0001HC-62 for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:22:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35056) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itb-0000tv-AG; Fri, 09 Jul 2021 01:17:51 -0400 Received: from ozlabs.org ([203.11.71.1]:34179) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itV-0001pD-L1; Fri, 09 Jul 2021 01:17:51 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd1Cl6z9sWd; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=xoc67/6UDUyRNCCPD8TosCLtaV2h3o1+SiaxBon11aI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hr5UbdQXQ4f73Ze31WDBJeQ6PKkaS/295SvI6W2yppsKeAuVp4JqfVjzRscpC0Gn2 apKvfNG15rItKx7QjPibWXI0LtJrpC7HD+SJW9/UK4NGqTeMShhUVS5fs5ay8nhrWg RxRG1X5txZSZz7YUlXhf/jXTFCFVLARsWMEyUczc= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 03/33] spapr: tune rtas-size Date: Fri, 9 Jul 2021 15:16:58 +1000 Message-Id: <20210709051728.170203-4-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Alexey Kardashevskiy QEMU reserves space for RTAS via /rtas/rtas-size which tells the client how much space the RTAS requires to work which includes the RTAS binary blob implementing RTAS runtime. Because pseries supports FWNMI which requires plenty of space, QEMU reserves more than 2KB which is enough for the RTAS blob as it is just 20 bytes (under QEMU). Since FWNMI reset delivery was added, RTAS_SIZE macro is not used anymore. This replaces RTAS_SIZE with RTAS_MIN_SIZE and uses it in the /rtas/rtas-size calculation to account for the RTAS blob. Fixes: 0e236d347790 ("ppc/spapr: Implement FWNMI System Reset delivery") Signed-off-by: Alexey Kardashevskiy Message-Id: <20210622070336.1463250-1-aik@ozlabs.ru> Reviewed-by: Greg Kurz Signed-off-by: David Gibson --- hw/ppc/spapr.c | 8 ++++++-- include/hw/ppc/spapr.h | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 4dd90b75cc..9e19c57032 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -919,9 +919,13 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt) * * The extra 8 bytes is required because Linux's FWNMI error log check * is off-by-one. + * + * RTAS_MIN_SIZE is required for the RTAS blob itself. */ - _FDT(fdt_setprop_cell(fdt, rtas, "rtas-size", RTAS_ERROR_LOG_MAX + - ms->smp.max_cpus * sizeof(uint64_t)*2 + sizeof(uint64_t))); + _FDT(fdt_setprop_cell(fdt, rtas, "rtas-size", RTAS_MIN_SIZE + + RTAS_ERROR_LOG_MAX + + ms->smp.max_cpus * sizeof(uint64_t) * 2 + + sizeof(uint64_t))); _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)); _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate", diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index f05219f75e..5697327e4c 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -770,7 +770,7 @@ void spapr_load_rtas(SpaprMachineState *spapr, void *fdt, hwaddr addr); #define SPAPR_IS_PCI_LIOBN(liobn) (!!((liobn) & 0x80000000)) #define SPAPR_PCI_DMA_WINDOW_NUM(liobn) ((liobn) & 0xff) -#define RTAS_SIZE 2048 +#define RTAS_MIN_SIZE 20 /* hv_rtas_size in SLOF */ #define RTAS_ERROR_LOG_MAX 2048 /* Offset from rtas-base where error log is placed */ From patchwork Fri Jul 9 05:16:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366711 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=-15.8 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,TVD_SUBJ_WIPE_DEBT,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 B37E5C11F66 for ; Fri, 9 Jul 2021 05:19:37 +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 398F661363 for ; Fri, 9 Jul 2021 05:19:37 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 398F661363 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:41536 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1ivI-0003ym-BN for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:19:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35024) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itY-0000rS-Au; Fri, 09 Jul 2021 01:17:48 -0400 Received: from ozlabs.org ([2401:3900:2:1::2]:37857) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itV-0001pF-La; Fri, 09 Jul 2021 01:17:48 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd1hYjz9sXJ; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=n0Z0Q61yySpmPXEN69QistWyZ7yE79j3dN2qMy7QRDY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=G0BiMrqpI2egm7GM/tKPDiJ7+R7K141pkwOUqk8WeLnTP9BYqPZUhE2s2xAb8IOTl yY9LFwv6myccSMBB07/0Gmjl41XpNO1cM9T0bLzK+Qo/thmqIcorY3h2RY+G57jEBT xGLLGWLzA6Bh5I3gzZFQJYHquXAn6b6Dc8Aij6Aw= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 04/33] target/ppc: Remove PowerPCCPUClass.handle_mmu_fault Date: Fri, 9 Jul 2021 15:16:59 +1000 Message-Id: <20210709051728.170203-5-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org X-Spam_score_int: -9 X-Spam_score: -1.0 X-Spam_bar: - X-Spam_report: (-1.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, TVD_SUBJ_WIPE_DEBT=1.004 autolearn=no 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: aik@ozlabs.ru, Richard Henderson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson Instead, use a switch on env->mmu_model. This avoids some replicated information in cpu setup. Signed-off-by: Richard Henderson Message-Id: <20210621125115.67717-2-bruno.larsen@eldorado.org.br> Reviewed-by: Greg Kurz Signed-off-by: David Gibson --- target/ppc/cpu-qom.h | 1 - target/ppc/cpu_init.c | 45 ----------------------------------------- target/ppc/mmu_helper.c | 24 ++++++++++++++++++---- 3 files changed, 20 insertions(+), 50 deletions(-) diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h index 7b424e3cb0..5800fa324e 100644 --- a/target/ppc/cpu-qom.h +++ b/target/ppc/cpu-qom.h @@ -198,7 +198,6 @@ struct PowerPCCPUClass { int n_host_threads; void (*init_proc)(CPUPPCState *env); int (*check_pow)(CPUPPCState *env); - int (*handle_mmu_fault)(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx); }; #ifndef CONFIG_USER_ONLY diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 1a22aef874..6f8ce010ba 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -4566,9 +4566,6 @@ POWERPC_FAMILY(601)(ObjectClass *oc, void *data) (1ull << MSR_IR) | (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_601; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->excp_model = POWERPC_EXCP_601; pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_601; @@ -4611,9 +4608,6 @@ POWERPC_FAMILY(601v)(ObjectClass *oc, void *data) (1ull << MSR_IR) | (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_601; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_601; pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK | POWERPC_FLAG_HID0_LE; @@ -4877,9 +4871,6 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void *data) (1ull << MSR_RI) | (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->excp_model = POWERPC_EXCP_604; pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_604; @@ -4961,9 +4952,6 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void *data) (1ull << MSR_RI) | (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->excp_model = POWERPC_EXCP_604; pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_604; @@ -5032,9 +5020,6 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void *data) (1ull << MSR_RI) | (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->excp_model = POWERPC_EXCP_7x0; pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_750; @@ -5112,9 +5097,6 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void *data) (1ull << MSR_RI) | (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->excp_model = POWERPC_EXCP_7x0; pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_750; @@ -5315,9 +5297,6 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data) (1ull << MSR_RI) | (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->excp_model = POWERPC_EXCP_7x0; pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_750; @@ -5398,9 +5377,6 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data) (1ull << MSR_RI) | (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->excp_model = POWERPC_EXCP_7x0; pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_750; @@ -5486,9 +5462,6 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data) (1ull << MSR_RI) | (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->excp_model = POWERPC_EXCP_7x0; pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_750; @@ -5574,9 +5547,6 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data) (1ull << MSR_RI) | (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->excp_model = POWERPC_EXCP_7x0; pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_750; @@ -5816,9 +5786,6 @@ POWERPC_FAMILY(7400)(ObjectClass *oc, void *data) (1ull << MSR_RI) | (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->excp_model = POWERPC_EXCP_74xx; pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_7400; @@ -5902,9 +5869,6 @@ POWERPC_FAMILY(7410)(ObjectClass *oc, void *data) (1ull << MSR_RI) | (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->excp_model = POWERPC_EXCP_74xx; pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_7400; @@ -6731,9 +6695,6 @@ POWERPC_FAMILY(e600)(ObjectClass *oc, void *data) (1ull << MSR_RI) | (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; -#if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; -#endif pcc->excp_model = POWERPC_EXCP_74xx; pcc->bus_model = PPC_FLAGS_INPUT_6xx; pcc->bfd_mach = bfd_mach_ppc_7400; @@ -7493,7 +7454,6 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data) (1ull << MSR_RI); pcc->mmu_model = POWERPC_MMU_64B; #if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; pcc->hash64_opts = &ppc_hash64_opts_basic; #endif pcc->excp_model = POWERPC_EXCP_970; @@ -7571,7 +7531,6 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data) LPCR_RMI | LPCR_HDICE; pcc->mmu_model = POWERPC_MMU_2_03; #if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; pcc->hash64_opts = &ppc_hash64_opts_basic; pcc->lrg_decr_bits = 32; #endif @@ -7715,7 +7674,6 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) pcc->lpcr_pm = LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2; pcc->mmu_model = POWERPC_MMU_2_06; #if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; pcc->hash64_opts = &ppc_hash64_opts_POWER7; pcc->lrg_decr_bits = 32; #endif @@ -7891,7 +7849,6 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data) LPCR_P8_PECE3 | LPCR_P8_PECE4; pcc->mmu_model = POWERPC_MMU_2_07; #if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; pcc->hash64_opts = &ppc_hash64_opts_POWER7; pcc->lrg_decr_bits = 32; pcc->n_host_threads = 8; @@ -8106,7 +8063,6 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE; pcc->mmu_model = POWERPC_MMU_3_00; #if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault; /* segment page size remain the same */ pcc->hash64_opts = &ppc_hash64_opts_POWER7; pcc->radix_page_info = &POWER9_radix_page_info; @@ -8317,7 +8273,6 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data) pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE; pcc->mmu_model = POWERPC_MMU_3_00; #if defined(CONFIG_SOFTMMU) - pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault; /* segment page size remain the same */ pcc->hash64_opts = &ppc_hash64_opts_POWER7; pcc->radix_page_info = &POWER10_radix_page_info; diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 1ecb36e85a..c4b1c93e47 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -2947,14 +2947,30 @@ bool ppc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, bool probe, uintptr_t retaddr) { PowerPCCPU *cpu = POWERPC_CPU(cs); - PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); CPUPPCState *env = &cpu->env; int ret; - if (pcc->handle_mmu_fault) { - ret = pcc->handle_mmu_fault(cpu, addr, access_type, mmu_idx); - } else { + switch (env->mmu_model) { +#if defined(TARGET_PPC64) + case POWERPC_MMU_64B: + case POWERPC_MMU_2_03: + case POWERPC_MMU_2_06: + case POWERPC_MMU_2_07: + ret = ppc_hash64_handle_mmu_fault(cpu, addr, access_type, mmu_idx); + break; + case POWERPC_MMU_3_00: + ret = ppc64_v3_handle_mmu_fault(cpu, addr, access_type, mmu_idx); + break; +#endif + + case POWERPC_MMU_32B: + case POWERPC_MMU_601: + ret = ppc_hash32_handle_mmu_fault(cpu, addr, access_type, mmu_idx); + break; + + default: ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx); + break; } if (unlikely(ret != 0)) { if (probe) { From patchwork Fri Jul 9 05:17:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366717 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.8 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 F0BE5C07E99 for ; Fri, 9 Jul 2021 05:23:09 +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 AAF0B6140F for ; Fri, 9 Jul 2021 05:23:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org AAF0B6140F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:51450 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1iyi-0002BN-T7 for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:23:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35096) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itc-0000wx-Sh; Fri, 09 Jul 2021 01:17:52 -0400 Received: from bilbo.ozlabs.org ([2401:3900:2:1::2]:51417 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1ita-0001vm-QO; Fri, 09 Jul 2021 01:17:52 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd1x3Lz9sXM; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=74urRj6f055VnsLsqp8XF+lYeV+epmK/BmGaLFdYfYQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=T7EZCNIqCOrFPw9+pTzkohv422HlrnDEeqTRAkKyqnGsIhubUQp3RmiAjTNTT2TaT B4vsEofpSZ1LQRgRFXBKkYpVkvxkb58CmvlsdsVxS2kPk/BNOjfyPM7n94HJCNAMcb WAZu6TNvqcZEpbjXl8b/YrBl2XjhsIgwFcFfH24I= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 05/33] target/ppc: Use MMUAccessType with *_handle_mmu_fault Date: Fri, 9 Jul 2021 15:17:00 +1000 Message-Id: <20210709051728.170203-6-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, Richard Henderson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson These changes were waiting until we didn't need to match the function type of PowerPCCPUClass.handle_mmu_fault. Signed-off-by: Richard Henderson Message-Id: <20210621125115.67717-3-bruno.larsen@eldorado.org.br> Reviewed-by: Greg Kurz Signed-off-by: David Gibson --- target/ppc/mmu-hash32.c | 7 ++----- target/ppc/mmu-hash32.h | 4 ++-- target/ppc/mmu-hash64.c | 6 +----- target/ppc/mmu-hash64.h | 4 ++-- target/ppc/mmu-radix64.c | 7 ++----- target/ppc/mmu-radix64.h | 4 ++-- 6 files changed, 11 insertions(+), 21 deletions(-) diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c index 9f0a497657..8f19b43e47 100644 --- a/target/ppc/mmu-hash32.c +++ b/target/ppc/mmu-hash32.c @@ -415,8 +415,8 @@ static hwaddr ppc_hash32_pte_raddr(target_ulong sr, ppc_hash_pte32_t pte, return (rpn & ~mask) | (eaddr & mask); } -int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, - int mmu_idx) +int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, + MMUAccessType access_type, int mmu_idx) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -425,11 +425,8 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, ppc_hash_pte32_t pte; int prot; int need_prot; - MMUAccessType access_type; hwaddr raddr; - assert((rwx == 0) || (rwx == 1) || (rwx == 2)); - access_type = rwx; need_prot = prot_for_access_type(access_type); /* 1. Handle real mode accesses */ diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h index 898021f0d8..30e35718a7 100644 --- a/target/ppc/mmu-hash32.h +++ b/target/ppc/mmu-hash32.h @@ -5,8 +5,8 @@ hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash); hwaddr ppc_hash32_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr); -int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, int rw, - int mmu_idx); +int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, + MMUAccessType access_type, int mmu_idx); /* * Segment register definitions diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index 708dffc31b..2febd369b1 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -874,7 +874,7 @@ static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb) } int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, - int rwx, int mmu_idx) + MMUAccessType access_type, int mmu_idx) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -884,13 +884,9 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, hwaddr ptex; ppc_hash_pte64_t pte; int exec_prot, pp_prot, amr_prot, prot; - MMUAccessType access_type; int need_prot; hwaddr raddr; - assert((rwx == 0) || (rwx == 1) || (rwx == 2)); - access_type = rwx; - /* * Note on LPCR usage: 970 uses HID4, but our special variant of * store_spr copies relevant fields into env->spr[SPR_LPCR]. diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h index 4b8b8e7950..3e8a8eec1f 100644 --- a/target/ppc/mmu-hash64.h +++ b/target/ppc/mmu-hash64.h @@ -8,8 +8,8 @@ void dump_slb(PowerPCCPU *cpu); int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot, target_ulong esid, target_ulong vsid); hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr); -int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, int rw, - int mmu_idx); +int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, + MMUAccessType access_type, int mmu_idx); void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong pte_index, target_ulong pte0, target_ulong pte1); diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index b6d191c1d8..1c707d387d 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -555,19 +555,16 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, return 0; } -int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, - int mmu_idx) +int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, + MMUAccessType access_type, int mmu_idx) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; int page_size, prot; bool relocation; - MMUAccessType access_type; hwaddr raddr; assert(!(msr_hv && cpu->vhyp)); - assert((rwx == 0) || (rwx == 1) || (rwx == 2)); - access_type = rwx; relocation = (access_type == MMU_INST_FETCH ? msr_ir : msr_dr); /* HV or virtual hypervisor Real Mode Access */ diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h index f28c5794d0..94bd72cb38 100644 --- a/target/ppc/mmu-radix64.h +++ b/target/ppc/mmu-radix64.h @@ -44,8 +44,8 @@ #ifdef TARGET_PPC64 -int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, - int mmu_idx); +int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, + MMUAccessType access_type, int mmu_idx); hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr); static inline int ppc_radix64_get_prot_eaa(uint64_t pte) From patchwork Fri Jul 9 05:17:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366719 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.8 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 BC02CC07E99 for ; Fri, 9 Jul 2021 05:24: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 3F99D6140F for ; Fri, 9 Jul 2021 05:24:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3F99D6140F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:56288 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j0O-0005SH-6h for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:24:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35114) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itd-0000z4-R7; Fri, 09 Jul 2021 01:17:53 -0400 Received: from ozlabs.org ([203.11.71.1]:33393) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itb-0001vb-4D; Fri, 09 Jul 2021 01:17:53 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd2Hplz9sXV; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=Iku9vdl3Hq8CB6046m3NqY9iWp2JnMKsY7XF89V88Xw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cEoDTa1+WMC4ekWSs7Iznj7tssMBzgzUTPydCSUX+bXPFHowEvZ+HpClYuka4/8x1 55R9fwiUljeTQQI3bJGIflkLR5IYjuzeyWSJzOjUkVr3dQ2EMXmBZ7MhvRYyp629/8 7dgYc6dvKQWBGpnKJOvVZrtjqoB3Aw7F2k543CUY= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 06/33] target/ppc: Push real-mode handling into ppc_radix64_xlate Date: Fri, 9 Jul 2021 15:17:01 +1000 Message-Id: <20210709051728.170203-7-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, Richard Henderson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson This removes some incomplete duplication between ppc_radix64_handle_mmu_fault and ppc_radix64_get_phys_page_debug. The former was correct wrt SPR_HRMOR and the latter was not. Signed-off-by: Richard Henderson Message-Id: <20210621125115.67717-4-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson --- target/ppc/mmu-radix64.c | 77 ++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 43 deletions(-) diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index 1c707d387d..dd5ae69052 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -465,7 +465,6 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, */ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, - bool relocation, hwaddr *raddr, int *psizep, int *protp, bool guest_visible) { @@ -474,6 +473,37 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, ppc_v3_pate_t pate; int psize, prot; hwaddr g_raddr; + bool relocation; + + assert(!(msr_hv && cpu->vhyp)); + + relocation = (access_type == MMU_INST_FETCH ? msr_ir : msr_dr); + + /* HV or virtual hypervisor Real Mode Access */ + if (!relocation && (msr_hv || cpu->vhyp)) { + /* In real mode top 4 effective addr bits (mostly) ignored */ + *raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL; + + /* In HV mode, add HRMOR if top EA bit is clear */ + if (msr_hv || !env->has_hv_mode) { + if (!(eaddr >> 63)) { + *raddr |= env->spr[SPR_HRMOR]; + } + } + *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + *psizep = TARGET_PAGE_BITS; + return 0; + } + + /* + * Check UPRT (we avoid the check in real mode to deal with + * transitional states during kexec. + */ + if (guest_visible && !ppc64_use_proc_tbl(cpu)) { + qemu_log_mask(LOG_GUEST_ERROR, + "LPCR:UPRT not set in radix mode ! LPCR=" + TARGET_FMT_lx "\n", env->spr[SPR_LPCR]); + } /* Virtual Mode Access - get the fully qualified address */ if (!ppc_radix64_get_fully_qualified_addr(&cpu->env, eaddr, &lpid, &pid)) { @@ -559,43 +589,11 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, int mmu_idx) { CPUState *cs = CPU(cpu); - CPUPPCState *env = &cpu->env; int page_size, prot; - bool relocation; hwaddr raddr; - assert(!(msr_hv && cpu->vhyp)); - - relocation = (access_type == MMU_INST_FETCH ? msr_ir : msr_dr); - /* HV or virtual hypervisor Real Mode Access */ - if (!relocation && (msr_hv || cpu->vhyp)) { - /* In real mode top 4 effective addr bits (mostly) ignored */ - raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL; - - /* In HV mode, add HRMOR if top EA bit is clear */ - if (msr_hv || !env->has_hv_mode) { - if (!(eaddr >> 63)) { - raddr |= env->spr[SPR_HRMOR]; - } - } - tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, - PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx, - TARGET_PAGE_SIZE); - return 0; - } - - /* - * Check UPRT (we avoid the check in real mode to deal with - * transitional states during kexec. - */ - if (!ppc64_use_proc_tbl(cpu)) { - qemu_log_mask(LOG_GUEST_ERROR, - "LPCR:UPRT not set in radix mode ! LPCR=" - TARGET_FMT_lx "\n", env->spr[SPR_LPCR]); - } - /* Translate eaddr to raddr (where raddr is addr qemu needs for access) */ - if (ppc_radix64_xlate(cpu, eaddr, access_type, relocation, &raddr, + if (ppc_radix64_xlate(cpu, eaddr, access_type, &raddr, &page_size, &prot, true)) { return 1; } @@ -607,18 +605,11 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) { - CPUPPCState *env = &cpu->env; int psize, prot; hwaddr raddr; - /* Handle Real Mode */ - if ((msr_dr == 0) && (msr_hv || cpu->vhyp)) { - /* In real mode top 4 effective addr bits (mostly) ignored */ - return eaddr & 0x0FFFFFFFFFFFFFFFULL; - } - - if (ppc_radix64_xlate(cpu, eaddr, 0, msr_dr, &raddr, &psize, - &prot, false)) { + if (ppc_radix64_xlate(cpu, eaddr, MMU_DATA_LOAD, &raddr, + &psize, &prot, false)) { return -1; } From patchwork Fri Jul 9 05:17:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366721 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.8 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 5AAD1C07E99 for ; Fri, 9 Jul 2021 05:26:39 +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 D8B096140F for ; Fri, 9 Jul 2021 05:26:38 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D8B096140F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59834 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j26-0000WT-0T for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:26:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35098) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itd-0000xL-03; Fri, 09 Jul 2021 01:17:53 -0400 Received: from bilbo.ozlabs.org ([2401:3900:2:1::2]:40195 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itb-0001w6-3e; Fri, 09 Jul 2021 01:17:52 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd3YwGz9sfR; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=W1hgkBfntpE0AVG54dGL+htM4AdTKAwQqPJZRbk5Sfg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Un/gFhqHayno7RWrnNUV6AvenIsHKERR5avajE2uMAQBkRuFR7IRpO/I3vn7PesPm OAD9r3gaXU7QvuV4R87sXJmdJ0jy8lojTCgLzI4imQTRIMoElRi63UajDf1967zWq8 YFyMnGNSwd8RhnsqOkMI8jcWNYOiV8zpbwWZtK1I= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 07/33] target/ppc: Use bool success for ppc_radix64_xlate Date: Fri, 9 Jul 2021 15:17:02 +1000 Message-Id: <20210709051728.170203-8-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, Richard Henderson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson Instead of returning non-zero for failure, return true for success. Signed-off-by: Richard Henderson Message-Id: <20210621125115.67717-5-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson --- target/ppc/mmu-radix64.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index dd5ae69052..2d5f0850c9 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -463,10 +463,10 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, * | = On | Process Scoped | Scoped | * +-------------+----------------+---------------+ */ -static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, - MMUAccessType access_type, - hwaddr *raddr, int *psizep, int *protp, - bool guest_visible) +static bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, + MMUAccessType access_type, + hwaddr *raddr, int *psizep, int *protp, + bool guest_visible) { CPUPPCState *env = &cpu->env; uint64_t lpid, pid; @@ -492,7 +492,7 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, } *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC; *psizep = TARGET_PAGE_BITS; - return 0; + return true; } /* @@ -510,7 +510,7 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, if (guest_visible) { ppc_radix64_raise_segi(cpu, access_type, eaddr); } - return 1; + return false; } /* Get Process Table */ @@ -523,13 +523,13 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, if (guest_visible) { ppc_radix64_raise_si(cpu, access_type, eaddr, DSISR_NOPTE); } - return 1; + return false; } if (!validate_pate(cpu, lpid, &pate)) { if (guest_visible) { ppc_radix64_raise_si(cpu, access_type, eaddr, DSISR_R_BADCONFIG); } - return 1; + return false; } } @@ -549,7 +549,7 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, pate, &g_raddr, &prot, &psize, guest_visible); if (ret) { - return ret; + return false; } *psizep = MIN(*psizep, psize); *protp &= prot; @@ -573,7 +573,7 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, &prot, &psize, false, guest_visible); if (ret) { - return ret; + return false; } *psizep = MIN(*psizep, psize); *protp &= prot; @@ -582,7 +582,7 @@ static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, } } - return 0; + return true; } int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, @@ -593,8 +593,8 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, hwaddr raddr; /* Translate eaddr to raddr (where raddr is addr qemu needs for access) */ - if (ppc_radix64_xlate(cpu, eaddr, access_type, &raddr, - &page_size, &prot, true)) { + if (!ppc_radix64_xlate(cpu, eaddr, access_type, &raddr, + &page_size, &prot, true)) { return 1; } @@ -608,8 +608,8 @@ hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) int psize, prot; hwaddr raddr; - if (ppc_radix64_xlate(cpu, eaddr, MMU_DATA_LOAD, &raddr, - &psize, &prot, false)) { + if (!ppc_radix64_xlate(cpu, eaddr, MMU_DATA_LOAD, &raddr, + &psize, &prot, false)) { return -1; } From patchwork Fri Jul 9 05:17:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366729 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.8 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 D3678C07E99 for ; Fri, 9 Jul 2021 05:29:11 +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 82E6A6140F for ; Fri, 9 Jul 2021 05:29:11 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 82E6A6140F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:40356 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j4Y-0006US-F9 for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:29:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35136) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1ite-00010b-Fk; Fri, 09 Jul 2021 01:17:54 -0400 Received: from bilbo.ozlabs.org ([2401:3900:2:1::2]:53853 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itb-0001w7-4D; Fri, 09 Jul 2021 01:17:54 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd3CPqz9sXb; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=y+DWT/pQ9IRFjQt7FV5diYd3SsCVc/rs2YsYjhQ+Phw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AmE7RbsdV15gUbP5zFMVaE3GNeQi4cxbg0iKtV6vHrzULkuvRX9og4f3IMOMp53wu itX1URJa2sge248ZeygXEVMjuMshuvNgudTrcbYHWmHsIfyZe0DVyufMphRlc29iuN ZpRUA9Vs/tuEqh6ba1xU50ylp/I7x1uJL+LNHAtc= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 08/33] target/ppc: Split out ppc_hash64_xlate Date: Fri, 9 Jul 2021 15:17:03 +1000 Message-Id: <20210709051728.170203-9-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, Richard Henderson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson Mirror the interface of ppc_radix64_xlate, putting all of the logic for hash64 translation into a single function. Signed-off-by: Richard Henderson Message-Id: <20210621125115.67717-6-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson --- target/ppc/mmu-hash64.c | 125 +++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 66 deletions(-) diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index 2febd369b1..c6b167b4dc 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -873,8 +873,10 @@ static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb) return -1; } -int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, - MMUAccessType access_type, int mmu_idx) +static bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, + MMUAccessType access_type, + hwaddr *raddrp, int *psizep, int *protp, + bool guest_visible) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -918,9 +920,11 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, slb = &vrma_slbe; if (build_vrma_slbe(cpu, slb) != 0) { /* Invalid VRMA setup, machine check */ - cs->exception_index = POWERPC_EXCP_MCHECK; - env->error_code = 0; - return 1; + if (guest_visible) { + cs->exception_index = POWERPC_EXCP_MCHECK; + env->error_code = 0; + } + return false; } goto skip_slb_search; @@ -929,6 +933,9 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, /* Emulated old-style RMO mode, bounds check against RMLS */ if (raddr >= limit) { + if (!guest_visible) { + return false; + } switch (access_type) { case MMU_INST_FETCH: ppc_hash64_set_isi(cs, SRR1_PROTFAULT); @@ -943,15 +950,16 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, default: g_assert_not_reached(); } - return 1; + return false; } raddr |= env->spr[SPR_RMOR]; } - tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, - PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx, - TARGET_PAGE_SIZE); - return 0; + + *raddrp = raddr; + *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + *psizep = TARGET_PAGE_BITS; + return true; } /* 2. Translation is on, so look up the SLB */ @@ -964,6 +972,9 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, exit(1); } /* Segment still not found, generate the appropriate interrupt */ + if (!guest_visible) { + return false; + } switch (access_type) { case MMU_INST_FETCH: cs->exception_index = POWERPC_EXCP_ISEG; @@ -978,20 +989,25 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, default: g_assert_not_reached(); } - return 1; + return false; } -skip_slb_search: + skip_slb_search: /* 3. Check for segment level no-execute violation */ if (access_type == MMU_INST_FETCH && (slb->vsid & SLB_VSID_N)) { - ppc_hash64_set_isi(cs, SRR1_NOEXEC_GUARD); - return 1; + if (guest_visible) { + ppc_hash64_set_isi(cs, SRR1_NOEXEC_GUARD); + } + return false; } /* 4. Locate the PTE in the hash table */ ptex = ppc_hash64_htab_lookup(cpu, slb, eaddr, &pte, &apshift); if (ptex == -1) { + if (!guest_visible) { + return false; + } switch (access_type) { case MMU_INST_FETCH: ppc_hash64_set_isi(cs, SRR1_NOPTE); @@ -1005,7 +1021,7 @@ skip_slb_search: default: g_assert_not_reached(); } - return 1; + return false; } qemu_log_mask(CPU_LOG_MMU, "found PTE at index %08" HWADDR_PRIx "\n", ptex); @@ -1021,6 +1037,9 @@ skip_slb_search: if (need_prot & ~prot) { /* Access right violation */ qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n"); + if (!guest_visible) { + return false; + } if (access_type == MMU_INST_FETCH) { int srr1 = 0; if (PAGE_EXEC & ~exec_prot) { @@ -1045,7 +1064,7 @@ skip_slb_search: } ppc_hash64_set_dsi(cs, eaddr, dsisr); } - return 1; + return false; } qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n"); @@ -1069,66 +1088,40 @@ skip_slb_search: /* 7. Determine the real address from the PTE */ - raddr = deposit64(pte.pte1 & HPTE64_R_RPN, 0, apshift, eaddr); - - tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, - prot, mmu_idx, 1ULL << apshift); - - return 0; + *raddrp = deposit64(pte.pte1 & HPTE64_R_RPN, 0, apshift, eaddr); + *protp = prot; + *psizep = apshift; + return true; } -hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr) +int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, + MMUAccessType access_type, int mmu_idx) { - CPUPPCState *env = &cpu->env; - ppc_slb_t vrma_slbe; - ppc_slb_t *slb; - hwaddr ptex, raddr; - ppc_hash_pte64_t pte; - unsigned apshift; + CPUState *cs = CPU(cpu); + int page_size, prot; + hwaddr raddr; - /* Handle real mode */ - if (msr_dr == 0) { - /* In real mode the top 4 effective address bits are ignored */ - raddr = addr & 0x0FFFFFFFFFFFFFFFULL; + if (!ppc_hash64_xlate(cpu, eaddr, access_type, &raddr, + &page_size, &prot, true)) { + return 1; + } - if (cpu->vhyp) { - /* - * In virtual hypervisor mode, there's nothing to do: - * EA == GPA == qemu guest address - */ - return raddr; - } else if ((msr_hv || !env->has_hv_mode) && !(addr >> 63)) { - /* In HV mode, add HRMOR if top EA bit is clear */ - return raddr | env->spr[SPR_HRMOR]; - } else if (ppc_hash64_use_vrma(env)) { - /* Emulated VRMA mode */ - slb = &vrma_slbe; - if (build_vrma_slbe(cpu, slb) != 0) { - return -1; - } - } else { - target_ulong limit = rmls_limit(cpu); + tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, + prot, mmu_idx, 1UL << page_size); + return 0; +} - /* Emulated old-style RMO mode, bounds check against RMLS */ - if (raddr >= limit) { - return -1; - } - return raddr | env->spr[SPR_RMOR]; - } - } else { - slb = slb_lookup(cpu, addr); - if (!slb) { - return -1; - } - } +hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) +{ + int psize, prot; + hwaddr raddr; - ptex = ppc_hash64_htab_lookup(cpu, slb, addr, &pte, &apshift); - if (ptex == -1) { + if (!ppc_hash64_xlate(cpu, eaddr, MMU_DATA_LOAD, &raddr, + &psize, &prot, false)) { return -1; } - return deposit64(pte.pte1 & HPTE64_R_RPN, 0, apshift, addr) - & TARGET_PAGE_MASK; + return raddr & TARGET_PAGE_MASK; } void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong ptex, From patchwork Fri Jul 9 05:17:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366723 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.8 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 864B4C07E99 for ; Fri, 9 Jul 2021 05:26:50 +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 072AA61002 for ; Fri, 9 Jul 2021 05:26:49 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 072AA61002 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:32896 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j2G-0001bW-6K for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:26:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35148) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itf-00011m-1Y; Fri, 09 Jul 2021 01:17:55 -0400 Received: from ozlabs.org ([203.11.71.1]:38495) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itb-0001wP-UG; Fri, 09 Jul 2021 01:17:54 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd4H4Bz9sjJ; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=cGFa/bncfPP5XoXpbY42QU0Tkk1WM8/Hmffo0dwmUM8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Miqmqo21X8H/rz05Z3p3CbBIKSmnh/LKjzTWmAFNTCv8QhSZlkiW2sfv9JbznNEL7 L+lsIbBlpQdxR9cUluFtJABSFRCOFkczMBgjzFx41ByuS9NkDfRHpnFOvcqLSdmqiE uf+M/WBAZzYcSgOZFkjU8mQDaOuVaxxvHwX1OKsM= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 09/33] target/ppc: Split out ppc_hash32_xlate Date: Fri, 9 Jul 2021 15:17:04 +1000 Message-Id: <20210709051728.170203-10-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, Richard Henderson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson Mirror the interface of ppc_radix64_xlate, putting all of the logic for hash32 translation into a single entry point. Signed-off-by: Richard Henderson Message-Id: <20210621125115.67717-7-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson --- target/ppc/mmu-hash32.c | 224 ++++++++++++++++++++-------------------- 1 file changed, 113 insertions(+), 111 deletions(-) diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c index 8f19b43e47..ad22372c07 100644 --- a/target/ppc/mmu-hash32.c +++ b/target/ppc/mmu-hash32.c @@ -218,10 +218,11 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea, return -1; } -static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr, - target_ulong eaddr, - MMUAccessType access_type, - hwaddr *raddr, int *prot) +static bool ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr, + target_ulong eaddr, + MMUAccessType access_type, + hwaddr *raddr, int *prot, + bool guest_visible) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -238,17 +239,23 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr, */ *raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF); *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - return 0; + return true; } if (access_type == MMU_INST_FETCH) { /* No code fetch is allowed in direct-store areas */ - cs->exception_index = POWERPC_EXCP_ISI; - env->error_code = 0x10000000; - return 1; + if (guest_visible) { + cs->exception_index = POWERPC_EXCP_ISI; + env->error_code = 0x10000000; + } + return false; } - switch (env->access_type) { + /* + * From ppc_cpu_get_phys_page_debug, env->access_type is not set. + * Assume ACCESS_INT for that case. + */ + switch (guest_visible ? env->access_type : ACCESS_INT) { case ACCESS_INT: /* Integer load/store : only access allowed */ break; @@ -257,7 +264,7 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr, cs->exception_index = POWERPC_EXCP_ALIGN; env->error_code = POWERPC_EXCP_ALIGN_FP; env->spr[SPR_DAR] = eaddr; - return 1; + return false; case ACCESS_RES: /* lwarx, ldarx or srwcx. */ env->error_code = 0; @@ -267,7 +274,7 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr, } else { env->spr[SPR_DSISR] = 0x04000000; } - return 1; + return false; case ACCESS_CACHE: /* * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi @@ -276,7 +283,7 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr, * no-op, it's quite easy :-) */ *raddr = eaddr; - return 0; + return true; case ACCESS_EXT: /* eciwx or ecowx */ cs->exception_index = POWERPC_EXCP_DSI; @@ -287,16 +294,18 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr, } else { env->spr[SPR_DSISR] = 0x04100000; } - return 1; + return false; default: - cpu_abort(cs, "ERROR: instruction should not need " - "address translation\n"); + cpu_abort(cs, "ERROR: insn should not need address translation\n"); } - if ((access_type == MMU_DATA_STORE || key != 1) && - (access_type == MMU_DATA_LOAD || key != 0)) { + + *prot = key ? PAGE_READ | PAGE_WRITE : PAGE_READ; + if (*prot & prot_for_access_type(access_type)) { *raddr = eaddr; - return 0; - } else { + return true; + } + + if (guest_visible) { cs->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; env->spr[SPR_DAR] = eaddr; @@ -305,8 +314,8 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr, } else { env->spr[SPR_DSISR] = 0x08000000; } - return 1; } + return false; } hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash) @@ -415,8 +424,10 @@ static hwaddr ppc_hash32_pte_raddr(target_ulong sr, ppc_hash_pte32_t pte, return (rpn & ~mask) | (eaddr & mask); } -int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, - MMUAccessType access_type, int mmu_idx) +static bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, + MMUAccessType access_type, + hwaddr *raddrp, int *psizep, int *protp, + bool guest_visible) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -427,43 +438,43 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int need_prot; hwaddr raddr; - need_prot = prot_for_access_type(access_type); + /* There are no hash32 large pages. */ + *psizep = TARGET_PAGE_BITS; /* 1. Handle real mode accesses */ if (access_type == MMU_INST_FETCH ? !msr_ir : !msr_dr) { /* Translation is off */ - raddr = eaddr; - tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, - PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx, - TARGET_PAGE_SIZE); - return 0; + *raddrp = eaddr; + *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + return true; } + need_prot = prot_for_access_type(access_type); + /* 2. Check Block Address Translation entries (BATs) */ if (env->nb_BATs != 0) { - raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, &prot); + raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, protp); if (raddr != -1) { - if (need_prot & ~prot) { - if (access_type == MMU_INST_FETCH) { - cs->exception_index = POWERPC_EXCP_ISI; - env->error_code = 0x08000000; - } else { - cs->exception_index = POWERPC_EXCP_DSI; - env->error_code = 0; - env->spr[SPR_DAR] = eaddr; - if (access_type == MMU_DATA_STORE) { - env->spr[SPR_DSISR] = 0x0a000000; + if (need_prot & ~*protp) { + if (guest_visible) { + if (access_type == MMU_INST_FETCH) { + cs->exception_index = POWERPC_EXCP_ISI; + env->error_code = 0x08000000; } else { - env->spr[SPR_DSISR] = 0x08000000; + cs->exception_index = POWERPC_EXCP_DSI; + env->error_code = 0; + env->spr[SPR_DAR] = eaddr; + if (access_type == MMU_DATA_STORE) { + env->spr[SPR_DSISR] = 0x0a000000; + } else { + env->spr[SPR_DSISR] = 0x08000000; + } } } - return 1; + return false; } - - tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, - raddr & TARGET_PAGE_MASK, prot, mmu_idx, - TARGET_PAGE_SIZE); - return 0; + *raddrp = raddr; + return true; } } @@ -472,42 +483,38 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, /* 4. Handle direct store segments */ if (sr & SR32_T) { - if (ppc_hash32_direct_store(cpu, sr, eaddr, access_type, - &raddr, &prot) == 0) { - tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, - raddr & TARGET_PAGE_MASK, prot, mmu_idx, - TARGET_PAGE_SIZE); - return 0; - } else { - return 1; - } + return ppc_hash32_direct_store(cpu, sr, eaddr, access_type, + raddrp, protp, guest_visible); } /* 5. Check for segment level no-execute violation */ if (access_type == MMU_INST_FETCH && (sr & SR32_NX)) { - cs->exception_index = POWERPC_EXCP_ISI; - env->error_code = 0x10000000; - return 1; + if (guest_visible) { + cs->exception_index = POWERPC_EXCP_ISI; + env->error_code = 0x10000000; + } + return false; } /* 6. Locate the PTE in the hash table */ pte_offset = ppc_hash32_htab_lookup(cpu, sr, eaddr, &pte); if (pte_offset == -1) { - if (access_type == MMU_INST_FETCH) { - cs->exception_index = POWERPC_EXCP_ISI; - env->error_code = 0x40000000; - } else { - cs->exception_index = POWERPC_EXCP_DSI; - env->error_code = 0; - env->spr[SPR_DAR] = eaddr; - if (access_type == MMU_DATA_STORE) { - env->spr[SPR_DSISR] = 0x42000000; + if (guest_visible) { + if (access_type == MMU_INST_FETCH) { + cs->exception_index = POWERPC_EXCP_ISI; + env->error_code = 0x40000000; } else { - env->spr[SPR_DSISR] = 0x40000000; + cs->exception_index = POWERPC_EXCP_DSI; + env->error_code = 0; + env->spr[SPR_DAR] = eaddr; + if (access_type == MMU_DATA_STORE) { + env->spr[SPR_DSISR] = 0x42000000; + } else { + env->spr[SPR_DSISR] = 0x40000000; + } } } - - return 1; + return false; } qemu_log_mask(CPU_LOG_MMU, "found PTE at offset %08" HWADDR_PRIx "\n", pte_offset); @@ -519,20 +526,22 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, if (need_prot & ~prot) { /* Access right violation */ qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n"); - if (access_type == MMU_INST_FETCH) { - cs->exception_index = POWERPC_EXCP_ISI; - env->error_code = 0x08000000; - } else { - cs->exception_index = POWERPC_EXCP_DSI; - env->error_code = 0; - env->spr[SPR_DAR] = eaddr; - if (access_type == MMU_DATA_STORE) { - env->spr[SPR_DSISR] = 0x0a000000; + if (guest_visible) { + if (access_type == MMU_INST_FETCH) { + cs->exception_index = POWERPC_EXCP_ISI; + env->error_code = 0x08000000; } else { - env->spr[SPR_DSISR] = 0x08000000; + cs->exception_index = POWERPC_EXCP_DSI; + env->error_code = 0; + env->spr[SPR_DAR] = eaddr; + if (access_type == MMU_DATA_STORE) { + env->spr[SPR_DSISR] = 0x0a000000; + } else { + env->spr[SPR_DSISR] = 0x08000000; + } } } - return 1; + return false; } qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n"); @@ -556,45 +565,38 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, /* 9. Determine the real address from the PTE */ - raddr = ppc_hash32_pte_raddr(sr, pte, eaddr); - - tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, - prot, mmu_idx, TARGET_PAGE_SIZE); - - return 0; + *raddrp = ppc_hash32_pte_raddr(sr, pte, eaddr); + *protp = prot; + return true; } -hwaddr ppc_hash32_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) +int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, + MMUAccessType access_type, int mmu_idx) { - CPUPPCState *env = &cpu->env; - target_ulong sr; - hwaddr pte_offset; - ppc_hash_pte32_t pte; - int prot; - - if (msr_dr == 0) { - /* Translation is off */ - return eaddr; - } + CPUState *cs = CPU(cpu); + int page_size, prot; + hwaddr raddr; - if (env->nb_BATs != 0) { - hwaddr raddr = ppc_hash32_bat_lookup(cpu, eaddr, 0, &prot); - if (raddr != -1) { - return raddr; - } + /* Translate eaddr to raddr (where raddr is addr qemu needs for access) */ + if (!ppc_hash32_xlate(cpu, eaddr, access_type, &raddr, + &page_size, &prot, true)) { + return 1; } - sr = env->sr[eaddr >> 28]; + tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, + prot, mmu_idx, 1UL << page_size); + return 0; +} - if (sr & SR32_T) { - /* FIXME: Add suitable debug support for Direct Store segments */ - return -1; - } +hwaddr ppc_hash32_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) +{ + int psize, prot; + hwaddr raddr; - pte_offset = ppc_hash32_htab_lookup(cpu, sr, eaddr, &pte); - if (pte_offset == -1) { + if (!ppc_hash32_xlate(cpu, eaddr, MMU_DATA_LOAD, &raddr, + &psize, &prot, false)) { return -1; } - return ppc_hash32_pte_raddr(sr, pte, eaddr) & TARGET_PAGE_MASK; + return raddr & TARGET_PAGE_MASK; } From patchwork Fri Jul 9 05:17:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366715 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.8 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 3F4A2C07E99 for ; Fri, 9 Jul 2021 05:22:56 +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 B753961363 for ; Fri, 9 Jul 2021 05:22:55 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B753961363 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:51252 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1iyU-00023H-IY for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:22:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35172) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itg-00013z-0i; Fri, 09 Jul 2021 01:17:56 -0400 Received: from ozlabs.org ([203.11.71.1]:41417) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itb-0001wQ-VN; Fri, 09 Jul 2021 01:17:55 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd3wY8z9sfG; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=Snpve8d0Wc9D6qGzUzjGM46o8/opPZnexMkT1NT3nQg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OrHVyYiOljJJKoO+Wc+A2vxDk2UeKAMIJyD5msdOMvJ4/OdD9xqqBG7F5rWXrg7G3 LvAOk/OxolQy4zvqdaYPZIv30rE3Lnr03BSlUvwc2cZFC1Phhty7fkYEPrDtW1CGG2 5OPUexyVpq2xIYrHJ1ZsEZT7XOUnW5SSS57t9c7w= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 10/33] target/ppc: Split out ppc_jumbo_xlate Date: Fri, 9 Jul 2021 15:17:05 +1000 Message-Id: <20210709051728.170203-11-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, Richard Henderson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson Mirror the interface of ppc_radix64_xlate (mostly), putting all of the logic for older mmu translation into a single entry point. For booke, we need to add mmu_idx to the xlate-style interface. Signed-off-by: Richard Henderson Message-Id: <20210621125115.67717-8-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson --- target/ppc/mmu_helper.c | 179 +++++++++++++++++++++------------------- 1 file changed, 96 insertions(+), 83 deletions(-) diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index c4b1c93e47..2e92deb105 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -1435,48 +1435,6 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, } #endif -hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) -{ - PowerPCCPU *cpu = POWERPC_CPU(cs); - CPUPPCState *env = &cpu->env; - mmu_ctx_t ctx; - - switch (env->mmu_model) { -#if defined(TARGET_PPC64) - case POWERPC_MMU_64B: - case POWERPC_MMU_2_03: - case POWERPC_MMU_2_06: - case POWERPC_MMU_2_07: - return ppc_hash64_get_phys_page_debug(cpu, addr); - case POWERPC_MMU_3_00: - return ppc64_v3_get_phys_page_debug(cpu, addr); -#endif - - case POWERPC_MMU_32B: - case POWERPC_MMU_601: - return ppc_hash32_get_phys_page_debug(cpu, addr); - - default: - ; - } - - if (unlikely(get_physical_address(env, &ctx, addr, MMU_DATA_LOAD, - ACCESS_INT) != 0)) { - - /* - * Some MMUs have separate TLBs for code and data. If we only - * try an ACCESS_INT, we may not be able to read instructions - * mapped by code TLBs, so we also try a ACCESS_CODE. - */ - if (unlikely(get_physical_address(env, &ctx, addr, MMU_INST_FETCH, - ACCESS_CODE) != 0)) { - return -1; - } - } - - return ctx.raddr & TARGET_PAGE_MASK; -} - static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address, MMUAccessType access_type, int mmu_idx) { @@ -1532,30 +1490,38 @@ static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address, } /* Perform address translation */ -static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, - MMUAccessType access_type, int mmu_idx) +/* TODO: Split this by mmu_model. */ +static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr, + MMUAccessType access_type, + hwaddr *raddrp, int *psizep, int *protp, + int mmu_idx, bool guest_visible) { - CPUState *cs = env_cpu(env); - PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; mmu_ctx_t ctx; int type; - int ret = 0; + int ret; if (access_type == MMU_INST_FETCH) { /* code access */ type = ACCESS_CODE; - } else { + } else if (guest_visible) { /* data access */ type = env->access_type; + } else { + type = ACCESS_INT; } - ret = get_physical_address_wtlb(env, &ctx, address, access_type, + + ret = get_physical_address_wtlb(env, &ctx, eaddr, access_type, type, mmu_idx); if (ret == 0) { - tlb_set_page(cs, address & TARGET_PAGE_MASK, - ctx.raddr & TARGET_PAGE_MASK, ctx.prot, - mmu_idx, TARGET_PAGE_SIZE); - ret = 0; - } else if (ret < 0) { + *raddrp = ctx.raddr; + *protp = ctx.prot; + *psizep = TARGET_PAGE_BITS; + return true; + } + + if (guest_visible) { LOG_MMU_STATE(cs); if (type == ACCESS_CODE) { switch (ret) { @@ -1565,7 +1531,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, case POWERPC_MMU_SOFT_6xx: cs->exception_index = POWERPC_EXCP_IFTLB; env->error_code = 1 << 18; - env->spr[SPR_IMISS] = address; + env->spr[SPR_IMISS] = eaddr; env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem; goto tlb_miss; case POWERPC_MMU_SOFT_74xx: @@ -1575,29 +1541,25 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, case POWERPC_MMU_SOFT_4xx_Z: cs->exception_index = POWERPC_EXCP_ITLB; env->error_code = 0; - env->spr[SPR_40x_DEAR] = address; + env->spr[SPR_40x_DEAR] = eaddr; env->spr[SPR_40x_ESR] = 0x00000000; break; case POWERPC_MMU_BOOKE206: - booke206_update_mas_tlb_miss(env, address, 2, mmu_idx); + booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx); /* fall through */ case POWERPC_MMU_BOOKE: cs->exception_index = POWERPC_EXCP_ITLB; env->error_code = 0; - env->spr[SPR_BOOKE_DEAR] = address; + env->spr[SPR_BOOKE_DEAR] = eaddr; env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, MMU_DATA_LOAD); - return -1; + break; case POWERPC_MMU_MPC8xx: - /* XXX: TODO */ cpu_abort(cs, "MPC8xx MMU model is not implemented\n"); - break; case POWERPC_MMU_REAL: cpu_abort(cs, "PowerPC in real mode should never raise " "any MMU exceptions\n"); - return -1; default: cpu_abort(cs, "Unknown or invalid MMU model\n"); - return -1; } break; case -2: @@ -1634,7 +1596,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, cs->exception_index = POWERPC_EXCP_DLTLB; env->error_code = 0; } - env->spr[SPR_DMISS] = address; + env->spr[SPR_DMISS] = eaddr; env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem; tlb_miss: env->error_code |= ctx.key << 19; @@ -1652,7 +1614,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, tlb_miss_74xx: /* Implement LRU algorithm */ env->error_code = ctx.key << 19; - env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) | + env->spr[SPR_TLBMISS] = (eaddr & ~((target_ulong)0x3)) | ((env->last_way + 1) & (env->nb_ways - 1)); env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem; break; @@ -1660,7 +1622,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, case POWERPC_MMU_SOFT_4xx_Z: cs->exception_index = POWERPC_EXCP_DTLB; env->error_code = 0; - env->spr[SPR_40x_DEAR] = address; + env->spr[SPR_40x_DEAR] = eaddr; if (access_type == MMU_DATA_STORE) { env->spr[SPR_40x_ESR] = 0x00800000; } else { @@ -1670,23 +1632,20 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, case POWERPC_MMU_MPC8xx: /* XXX: TODO */ cpu_abort(cs, "MPC8xx MMU model is not implemented\n"); - break; case POWERPC_MMU_BOOKE206: - booke206_update_mas_tlb_miss(env, address, access_type, mmu_idx); + booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx); /* fall through */ case POWERPC_MMU_BOOKE: cs->exception_index = POWERPC_EXCP_DTLB; env->error_code = 0; - env->spr[SPR_BOOKE_DEAR] = address; + env->spr[SPR_BOOKE_DEAR] = eaddr; env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type); - return -1; + break; case POWERPC_MMU_REAL: cpu_abort(cs, "PowerPC in real mode should never raise " "any MMU exceptions\n"); - return -1; default: cpu_abort(cs, "Unknown or invalid MMU model\n"); - return -1; } break; case -2: @@ -1695,16 +1654,16 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, env->error_code = 0; if (env->mmu_model == POWERPC_MMU_SOFT_4xx || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) { - env->spr[SPR_40x_DEAR] = address; + env->spr[SPR_40x_DEAR] = eaddr; if (access_type == MMU_DATA_STORE) { env->spr[SPR_40x_ESR] |= 0x00800000; } } else if ((env->mmu_model == POWERPC_MMU_BOOKE) || (env->mmu_model == POWERPC_MMU_BOOKE206)) { - env->spr[SPR_BOOKE_DEAR] = address; + env->spr[SPR_BOOKE_DEAR] = eaddr; env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type); } else { - env->spr[SPR_DAR] = address; + env->spr[SPR_DAR] = eaddr; if (access_type == MMU_DATA_STORE) { env->spr[SPR_DSISR] = 0x0A000000; } else { @@ -1719,13 +1678,13 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, /* Floating point load/store */ cs->exception_index = POWERPC_EXCP_ALIGN; env->error_code = POWERPC_EXCP_ALIGN_FP; - env->spr[SPR_DAR] = address; + env->spr[SPR_DAR] = eaddr; break; case ACCESS_RES: /* lwarx, ldarx or stwcx. */ cs->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; - env->spr[SPR_DAR] = address; + env->spr[SPR_DAR] = eaddr; if (access_type == MMU_DATA_STORE) { env->spr[SPR_DSISR] = 0x06000000; } else { @@ -1736,7 +1695,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, /* eciwx or ecowx */ cs->exception_index = POWERPC_EXCP_DSI; env->error_code = 0; - env->spr[SPR_DAR] = address; + env->spr[SPR_DAR] = eaddr; if (access_type == MMU_DATA_STORE) { env->spr[SPR_DSISR] = 0x06100000; } else { @@ -1748,16 +1707,14 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, cs->exception_index = POWERPC_EXCP_PROGRAM; env->error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL; - env->spr[SPR_DAR] = address; + env->spr[SPR_DAR] = eaddr; break; } break; } } - ret = 1; } - - return ret; + return false; } #ifdef CONFIG_TCG @@ -2942,6 +2899,62 @@ void helper_check_tlb_flush_global(CPUPPCState *env) /*****************************************************************************/ +static int cpu_ppc_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, + MMUAccessType access_type, int mmu_idx) +{ + CPUState *cs = CPU(cpu); + int page_size, prot; + hwaddr raddr; + + if (!ppc_jumbo_xlate(cpu, eaddr, access_type, &raddr, + &page_size, &prot, mmu_idx, true)) { + return 1; + } + + tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, + prot, mmu_idx, 1UL << page_size); + return 0; +} + +hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + hwaddr raddr; + int s, p; + + switch (env->mmu_model) { +#if defined(TARGET_PPC64) + case POWERPC_MMU_64B: + case POWERPC_MMU_2_03: + case POWERPC_MMU_2_06: + case POWERPC_MMU_2_07: + return ppc_hash64_get_phys_page_debug(cpu, addr); + case POWERPC_MMU_3_00: + return ppc64_v3_get_phys_page_debug(cpu, addr); +#endif + + case POWERPC_MMU_32B: + case POWERPC_MMU_601: + return ppc_hash32_get_phys_page_debug(cpu, addr); + + default: + ; + } + + /* + * Some MMUs have separate TLBs for code and data. If we only + * try an MMU_DATA_LOAD, we may not be able to read instructions + * mapped by code TLBs, so we also try a MMU_INST_FETCH. + */ + if (ppc_jumbo_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p, 0, false) || + ppc_jumbo_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p, 0, false)) { + return raddr & TARGET_PAGE_MASK; + } + return -1; +} + + bool ppc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr) @@ -2969,7 +2982,7 @@ bool ppc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, break; default: - ret = cpu_ppc_handle_mmu_fault(env, addr, access_type, mmu_idx); + ret = cpu_ppc_handle_mmu_fault(cpu, addr, access_type, mmu_idx); break; } if (unlikely(ret != 0)) { From patchwork Fri Jul 9 05:17:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366731 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.8 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 E00B0C07E99 for ; Fri, 9 Jul 2021 05:29:43 +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 869F6613FD for ; Fri, 9 Jul 2021 05:29:43 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 869F6613FD Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:42686 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j54-0008C2-NK for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:29:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35198) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1ith-00017I-N5; Fri, 09 Jul 2021 01:17:57 -0400 Received: from ozlabs.org ([203.11.71.1]:47153) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itc-0001wt-Hk; Fri, 09 Jul 2021 01:17:57 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd4dZVz9shx; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=aYdgJgoexbLVbdW5sTv/Y2EbgQY5MU5mSQ15vaJDP6A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TxhRExFi4U2oNd/NtFDEXpqyWe8+UkXJbwas2rNxJ+idp1lDHRY0DPmNM5VGeFNt2 dyTeYp/uRWiJVoSBysskD7HjcuvDnmIoq9jR1rZrBqM7g0yOtaHBz/He0kWURhiSZ8 0NThSXcTpD2XfgIpaG1HLvMkCoZxYRxs0ASTFfZk= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 11/33] target/ppc: Introduce ppc_xlate Date: Fri, 9 Jul 2021 15:17:06 +1000 Message-Id: <20210709051728.170203-12-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, Richard Henderson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson Create one common dispatch for all of the ppc_*_xlate functions. Use ppc64_v3_radix to directly dispatch between ppc_radix64_xlate and ppc_hash64_xlate. Remove the separate *_handle_mmu_fault and *_get_phys_page_debug functions, using common code for ppc_cpu_tlb_fill and ppc_cpu_get_phys_page_debug. Signed-off-by: Richard Henderson Message-Id: <20210621125115.67717-9-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson --- target/ppc/mmu-book3s-v3.c | 19 ------- target/ppc/mmu-book3s-v3.h | 5 -- target/ppc/mmu-hash32.c | 38 ++------------ target/ppc/mmu-hash32.h | 6 +-- target/ppc/mmu-hash64.c | 37 ++------------ target/ppc/mmu-hash64.h | 6 +-- target/ppc/mmu-radix64.c | 38 ++------------ target/ppc/mmu-radix64.h | 6 +-- target/ppc/mmu_helper.c | 100 ++++++++++++++----------------------- 9 files changed, 55 insertions(+), 200 deletions(-) diff --git a/target/ppc/mmu-book3s-v3.c b/target/ppc/mmu-book3s-v3.c index c78fd8dc0e..f4985bae78 100644 --- a/target/ppc/mmu-book3s-v3.c +++ b/target/ppc/mmu-book3s-v3.c @@ -23,25 +23,6 @@ #include "mmu-book3s-v3.h" #include "mmu-radix64.h" -int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, - int mmu_idx) -{ - if (ppc64_v3_radix(cpu)) { /* Guest uses radix */ - return ppc_radix64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx); - } else { /* Guest uses hash */ - return ppc_hash64_handle_mmu_fault(cpu, eaddr, rwx, mmu_idx); - } -} - -hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr) -{ - if (ppc64_v3_radix(cpu)) { - return ppc_radix64_get_phys_page_debug(cpu, eaddr); - } else { - return ppc_hash64_get_phys_page_debug(cpu, eaddr); - } -} - bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, ppc_v3_pate_t *entry) { uint64_t patb = cpu->env.spr[SPR_PTCR] & PTCR_PATB; diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h index 7b89be54b8..a1326df969 100644 --- a/target/ppc/mmu-book3s-v3.h +++ b/target/ppc/mmu-book3s-v3.h @@ -67,11 +67,6 @@ static inline bool ppc64_v3_radix(PowerPCCPU *cpu) return !!(cpu->env.spr[SPR_LPCR] & LPCR_HR); } -hwaddr ppc64_v3_get_phys_page_debug(PowerPCCPU *cpu, vaddr eaddr); - -int ppc64_v3_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, - int mmu_idx); - static inline hwaddr ppc_hash64_hpt_base(PowerPCCPU *cpu) { uint64_t base; diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c index ad22372c07..6a07c345e4 100644 --- a/target/ppc/mmu-hash32.c +++ b/target/ppc/mmu-hash32.c @@ -424,10 +424,9 @@ static hwaddr ppc_hash32_pte_raddr(target_ulong sr, ppc_hash_pte32_t pte, return (rpn & ~mask) | (eaddr & mask); } -static bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, - MMUAccessType access_type, - hwaddr *raddrp, int *psizep, int *protp, - bool guest_visible) +bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, + hwaddr *raddrp, int *psizep, int *protp, + bool guest_visible) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -569,34 +568,3 @@ static bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, *protp = prot; return true; } - -int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, - MMUAccessType access_type, int mmu_idx) -{ - CPUState *cs = CPU(cpu); - int page_size, prot; - hwaddr raddr; - - /* Translate eaddr to raddr (where raddr is addr qemu needs for access) */ - if (!ppc_hash32_xlate(cpu, eaddr, access_type, &raddr, - &page_size, &prot, true)) { - return 1; - } - - tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, - prot, mmu_idx, 1UL << page_size); - return 0; -} - -hwaddr ppc_hash32_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) -{ - int psize, prot; - hwaddr raddr; - - if (!ppc_hash32_xlate(cpu, eaddr, MMU_DATA_LOAD, &raddr, - &psize, &prot, false)) { - return -1; - } - - return raddr & TARGET_PAGE_MASK; -} diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h index 30e35718a7..8694eccabd 100644 --- a/target/ppc/mmu-hash32.h +++ b/target/ppc/mmu-hash32.h @@ -4,9 +4,9 @@ #ifndef CONFIG_USER_ONLY hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash); -hwaddr ppc_hash32_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr); -int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, - MMUAccessType access_type, int mmu_idx); +bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, + hwaddr *raddrp, int *psizep, int *protp, + bool guest_visible); /* * Segment register definitions diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index c6b167b4dc..c1b98a97e9 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -873,10 +873,9 @@ static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb) return -1; } -static bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, - MMUAccessType access_type, - hwaddr *raddrp, int *psizep, int *protp, - bool guest_visible) +bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, + hwaddr *raddrp, int *psizep, int *protp, + bool guest_visible) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -1094,36 +1093,6 @@ static bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, return true; } -int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, - MMUAccessType access_type, int mmu_idx) -{ - CPUState *cs = CPU(cpu); - int page_size, prot; - hwaddr raddr; - - if (!ppc_hash64_xlate(cpu, eaddr, access_type, &raddr, - &page_size, &prot, true)) { - return 1; - } - - tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, - prot, mmu_idx, 1UL << page_size); - return 0; -} - -hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) -{ - int psize, prot; - hwaddr raddr; - - if (!ppc_hash64_xlate(cpu, eaddr, MMU_DATA_LOAD, &raddr, - &psize, &prot, false)) { - return -1; - } - - return raddr & TARGET_PAGE_MASK; -} - void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong ptex, target_ulong pte0, target_ulong pte1) { diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h index 3e8a8eec1f..9f338e1fe9 100644 --- a/target/ppc/mmu-hash64.h +++ b/target/ppc/mmu-hash64.h @@ -7,9 +7,9 @@ void dump_slb(PowerPCCPU *cpu); int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot, target_ulong esid, target_ulong vsid); -hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr); -int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, - MMUAccessType access_type, int mmu_idx); +bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, + hwaddr *raddrp, int *psizep, int *protp, + bool guest_visible); void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong pte_index, target_ulong pte0, target_ulong pte1); diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index 2d5f0850c9..cbd404bfa4 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -463,10 +463,9 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, * | = On | Process Scoped | Scoped | * +-------------+----------------+---------------+ */ -static bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, - MMUAccessType access_type, - hwaddr *raddr, int *psizep, int *protp, - bool guest_visible) +bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, + hwaddr *raddr, int *psizep, int *protp, + bool guest_visible) { CPUPPCState *env = &cpu->env; uint64_t lpid, pid; @@ -584,34 +583,3 @@ static bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, return true; } - -int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, - MMUAccessType access_type, int mmu_idx) -{ - CPUState *cs = CPU(cpu); - int page_size, prot; - hwaddr raddr; - - /* Translate eaddr to raddr (where raddr is addr qemu needs for access) */ - if (!ppc_radix64_xlate(cpu, eaddr, access_type, &raddr, - &page_size, &prot, true)) { - return 1; - } - - tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, - prot, mmu_idx, 1UL << page_size); - return 0; -} - -hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr) -{ - int psize, prot; - hwaddr raddr; - - if (!ppc_radix64_xlate(cpu, eaddr, MMU_DATA_LOAD, &raddr, - &psize, &prot, false)) { - return -1; - } - - return raddr & TARGET_PAGE_MASK; -} diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h index 94bd72cb38..6b13b89b64 100644 --- a/target/ppc/mmu-radix64.h +++ b/target/ppc/mmu-radix64.h @@ -44,9 +44,9 @@ #ifdef TARGET_PPC64 -int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, - MMUAccessType access_type, int mmu_idx); -hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr); +bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, + hwaddr *raddr, int *psizep, int *protp, + bool guest_visible); static inline int ppc_radix64_get_prot_eaa(uint64_t pte) { diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 2e92deb105..a0e4e027d3 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -2899,98 +2899,72 @@ void helper_check_tlb_flush_global(CPUPPCState *env) /*****************************************************************************/ -static int cpu_ppc_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, - MMUAccessType access_type, int mmu_idx) +static bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, + hwaddr *raddrp, int *psizep, int *protp, + int mmu_idx, bool guest_visible) { - CPUState *cs = CPU(cpu); - int page_size, prot; - hwaddr raddr; - - if (!ppc_jumbo_xlate(cpu, eaddr, access_type, &raddr, - &page_size, &prot, mmu_idx, true)) { - return 1; - } - - tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, - prot, mmu_idx, 1UL << page_size); - return 0; -} - -hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) -{ - PowerPCCPU *cpu = POWERPC_CPU(cs); - CPUPPCState *env = &cpu->env; - hwaddr raddr; - int s, p; - - switch (env->mmu_model) { + switch (cpu->env.mmu_model) { #if defined(TARGET_PPC64) + case POWERPC_MMU_3_00: + if (ppc64_v3_radix(cpu)) { + return ppc_radix64_xlate(cpu, eaddr, access_type, + raddrp, psizep, protp, guest_visible); + } + /* fall through */ case POWERPC_MMU_64B: case POWERPC_MMU_2_03: case POWERPC_MMU_2_06: case POWERPC_MMU_2_07: - return ppc_hash64_get_phys_page_debug(cpu, addr); - case POWERPC_MMU_3_00: - return ppc64_v3_get_phys_page_debug(cpu, addr); + return ppc_hash64_xlate(cpu, eaddr, access_type, + raddrp, psizep, protp, guest_visible); #endif case POWERPC_MMU_32B: case POWERPC_MMU_601: - return ppc_hash32_get_phys_page_debug(cpu, addr); + return ppc_hash32_xlate(cpu, eaddr, access_type, + raddrp, psizep, protp, guest_visible); default: - ; + return ppc_jumbo_xlate(cpu, eaddr, access_type, raddrp, + psizep, protp, mmu_idx, guest_visible); } +} + +hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + hwaddr raddr; + int s, p; /* * Some MMUs have separate TLBs for code and data. If we only * try an MMU_DATA_LOAD, we may not be able to read instructions * mapped by code TLBs, so we also try a MMU_INST_FETCH. */ - if (ppc_jumbo_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p, 0, false) || - ppc_jumbo_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p, 0, false)) { + if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p, 0, false) || + ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p, 0, false)) { return raddr & TARGET_PAGE_MASK; } return -1; } - -bool ppc_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, +bool ppc_cpu_tlb_fill(CPUState *cs, vaddr eaddr, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr) { PowerPCCPU *cpu = POWERPC_CPU(cs); - CPUPPCState *env = &cpu->env; - int ret; - - switch (env->mmu_model) { -#if defined(TARGET_PPC64) - case POWERPC_MMU_64B: - case POWERPC_MMU_2_03: - case POWERPC_MMU_2_06: - case POWERPC_MMU_2_07: - ret = ppc_hash64_handle_mmu_fault(cpu, addr, access_type, mmu_idx); - break; - case POWERPC_MMU_3_00: - ret = ppc64_v3_handle_mmu_fault(cpu, addr, access_type, mmu_idx); - break; -#endif - - case POWERPC_MMU_32B: - case POWERPC_MMU_601: - ret = ppc_hash32_handle_mmu_fault(cpu, addr, access_type, mmu_idx); - break; + hwaddr raddr; + int page_size, prot; - default: - ret = cpu_ppc_handle_mmu_fault(cpu, addr, access_type, mmu_idx); - break; + if (ppc_xlate(cpu, eaddr, access_type, &raddr, + &page_size, &prot, mmu_idx, !probe)) { + tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, + prot, mmu_idx, 1UL << page_size); + return true; } - if (unlikely(ret != 0)) { - if (probe) { - return false; - } - raise_exception_err_ra(env, cs->exception_index, env->error_code, - retaddr); + if (probe) { + return false; } - return true; + raise_exception_err_ra(&cpu->env, cs->exception_index, + cpu->env.error_code, retaddr); } From patchwork Fri Jul 9 05:17:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366737 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.8 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 B5002C07E99 for ; Fri, 9 Jul 2021 05:31:49 +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 5EF8661441 for ; Fri, 9 Jul 2021 05:31:49 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5EF8661441 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:49918 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j76-0005Fy-Hj for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:31:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35178) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itg-00014O-7w; Fri, 09 Jul 2021 01:17:56 -0400 Received: from bilbo.ozlabs.org ([2401:3900:2:1::2]:52645 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1ite-0001yC-3q; Fri, 09 Jul 2021 01:17:55 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd4whpz9srX; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=VUe7ZSHiWg41MtgkPuVTCh1/VfI/d8Vldeew52mc0ok=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c1ZmfHKGx3iVbjswwbl+5GBxH7cvRxmOEoz80L9L9DeBBfc8+Djux4TmFMFYeFDW1 eZ/vRRk8Saj0tKr3P3jZ7vJPqxGxpjIeyowxGXI6O9wIGoC5GmlV/PVg7E1n57XTPq ujR5W3i5w4ihB+qKTxWUtqf0hwjjUDo8MGYhAm9k= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 12/33] target/ppc: Restrict ppc_cpu_tlb_fill to TCG Date: Fri, 9 Jul 2021 15:17:07 +1000 Message-Id: <20210709051728.170203-13-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, Richard Henderson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson This function is used by TCGCPUOps, and is thus TCG specific. Signed-off-by: Richard Henderson Message-Id: <20210621125115.67717-10-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson --- target/ppc/mmu_helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index a0e4e027d3..ba1952c77d 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -2948,6 +2948,7 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) return -1; } +#ifdef CONFIG_TCG bool ppc_cpu_tlb_fill(CPUState *cs, vaddr eaddr, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr) @@ -2968,3 +2969,4 @@ bool ppc_cpu_tlb_fill(CPUState *cs, vaddr eaddr, int size, raise_exception_err_ra(&cpu->env, cs->exception_index, cpu->env.error_code, retaddr); } +#endif From patchwork Fri Jul 9 05:17:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366745 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.8 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 0FE0CC07E99 for ; Fri, 9 Jul 2021 05:34:37 +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 36AE261433 for ; Fri, 9 Jul 2021 05:34:36 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 36AE261433 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59272 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j9n-0002ym-5F for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:34:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35192) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1ith-00016T-6S; Fri, 09 Jul 2021 01:17:57 -0400 Received: from ozlabs.org ([203.11.71.1]:34805) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itf-0001yf-AN; Fri, 09 Jul 2021 01:17:56 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd5Ltxz9ssD; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=/MjHtqGSB4Q/DmQu+dP0YOXEQ18HZGJxu+t5gCrxzks=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ivJNesiNisrwDEuDwm0jc9PmO7a8gmnDWHPiOLUmKPjzr6qttptiBlNJWI2qBeYGx M5UGlXa0wLE7GHXiOCVIYU/4tqlcwGdShw4I82Xhl9feajQjgH99dDYDVNEbC1+JHk kMxoDLf1yXC1adFidtMtGoluu3Qpzh4tiRKyxs7s= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 13/33] target/ppc: Fix compilation with DUMP_PAGE_TABLES debug option Date: Fri, 9 Jul 2021 15:17:08 +1000 Message-Id: <20210709051728.170203-14-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, Fabiano Rosas Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Fabiano Rosas ../target/ppc/mmu_helper.c: In function 'get_segment_6xx_tlb': ../target/ppc/mmu_helper.c:514:46: error: passing argument 1 of 'ppc_hash32_hpt_mask' from incompatible pointer type [-Werror=incompatible-pointer-types] 514 | ppc_hash32_hpt_mask(env) + 0x80); | ^~~ | | | CPUPPCState * Fixes: 36778660d7 ("target/ppc: Eliminate htab_base and htab_mask variables") Signed-off-by: Fabiano Rosas Message-Id: <20210702215235.1941771-2-farosas@linux.ibm.com> Signed-off-by: David Gibson --- target/ppc/mmu_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index ba1952c77d..4c534b534b 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -511,7 +511,7 @@ static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx "\n", ppc_hash32_hpt_base(cpu), - ppc_hash32_hpt_mask(env) + 0x80); + ppc_hash32_hpt_mask(cpu) + 0x80); for (curaddr = ppc_hash32_hpt_base(cpu); curaddr < (ppc_hash32_hpt_base(cpu) + ppc_hash32_hpt_mask(cpu) + 0x80); From patchwork Fri Jul 9 05:17:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366753 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.8 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 25C03C07E99 for ; Fri, 9 Jul 2021 05:37:47 +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 B589561442 for ; Fri, 9 Jul 2021 05:37:46 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B589561442 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:39666 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jCr-0000Gn-QS for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:37:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35208) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iti-00018C-3Z; Fri, 09 Jul 2021 01:17:58 -0400 Received: from ozlabs.org ([203.11.71.1]:55519) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itf-0001yh-F7; Fri, 09 Jul 2021 01:17:57 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd5f4Fz9svs; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=hPtLEx8NTO2XmDISUnsJ9dDKsbJkzDbCv2e7woM/dQc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aOHeITflUyRCK2vf8jFFnluAqb0LEVzM94cieab9QbR6bPDY7gyTvx1bIv38d+03U OEq4zzVkoq7gcEnrwXEX1jE7S0nSV2e+vCy7YuxNsal1s6IokQCZcWKWfySwtYoadq H7PN2cE8GVobiX+I6PO+pmGadusywaw7mq4Bvun4= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 14/33] target/ppc: Fix compilation with FLUSH_ALL_TLBS debug option Date: Fri, 9 Jul 2021 15:17:09 +1000 Message-Id: <20210709051728.170203-15-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, Fabiano Rosas Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Fabiano Rosas ../target/ppc/mmu_helper.c: In function 'helper_store_ibatu': ../target/ppc/mmu_helper.c:1802:17: error: unused variable 'cpu' [-Werror=unused-variable] 1802 | PowerPCCPU *cpu = env_archcpu(env); | ^~~ ../target/ppc/mmu_helper.c: In function 'helper_store_dbatu': ../target/ppc/mmu_helper.c:1838:17: error: unused variable 'cpu' [-Werror=unused-variable] 1838 | PowerPCCPU *cpu = env_archcpu(env); | ^~~ ../target/ppc/mmu_helper.c: In function 'helper_store_601_batu': ../target/ppc/mmu_helper.c:1874:17: error: unused variable 'cpu' [-Werror=unused-variable] 1874 | PowerPCCPU *cpu = env_archcpu(env); | ^~~ ../target/ppc/mmu_helper.c: In function 'helper_store_601_batl': ../target/ppc/mmu_helper.c:1919:17: error: unused variable 'cpu' [-Werror=unused-variable] 1919 | PowerPCCPU *cpu = env_archcpu(env); Fixes: db70b31144 ("target/ppc: Use env_cpu, env_archcpu") Signed-off-by: Fabiano Rosas Message-Id: <20210702215235.1941771-3-farosas@linux.ibm.com> Signed-off-by: David Gibson --- target/ppc/mmu_helper.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 4c534b534b..945ac41d42 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -1755,9 +1755,6 @@ static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr, void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value) { target_ulong mask; -#if defined(FLUSH_ALL_TLBS) - PowerPCCPU *cpu = env_archcpu(env); -#endif dump_store_bat(env, 'I', 0, nr, value); if (env->IBAT[0][nr] != value) { @@ -1791,9 +1788,6 @@ void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value) void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value) { target_ulong mask; -#if defined(FLUSH_ALL_TLBS) - PowerPCCPU *cpu = env_archcpu(env); -#endif dump_store_bat(env, 'D', 0, nr, value); if (env->DBAT[0][nr] != value) { @@ -1828,7 +1822,6 @@ void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value) { target_ulong mask; #if defined(FLUSH_ALL_TLBS) - PowerPCCPU *cpu = env_archcpu(env); int do_inval; #endif @@ -1873,7 +1866,6 @@ void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value) #if !defined(FLUSH_ALL_TLBS) target_ulong mask; #else - PowerPCCPU *cpu = env_archcpu(env); int do_inval; #endif From patchwork Fri Jul 9 05:17:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366725 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.8 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 33327C07E99 for ; Fri, 9 Jul 2021 05:27:07 +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 E58546140F for ; Fri, 9 Jul 2021 05:27:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E58546140F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:33882 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j2Y-0002F2-54 for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:27:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35224) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iti-00019C-Ne; Fri, 09 Jul 2021 01:17:58 -0400 Received: from ozlabs.org ([2401:3900:2:1::2]:53671) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itg-0001zW-N1; Fri, 09 Jul 2021 01:17:58 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd60mRz9sxS; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=LfqnIK50XMbUbpPBuaN2qzQ6g1BvDI+U6oJFJ+G6lyI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AzbRKln7U3K/lJcWIsg+VDR2fvXL6ofrqZSFqra0go+YIbW6XD+I9GcIYj8IQjQ4S xPI+NDLp40ekt3ba0xERru1bgldrvGq0U42ETQiTw5eLmgLqJOVpjtbWFlOohGEiPG s/Cdgpowz3ma/iWzvXoJUBZ1MLEuFfFhmfhp1W/s= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 15/33] target/ppc: Fix compilation with DEBUG_BATS debug option Date: Fri, 9 Jul 2021 15:17:10 +1000 Message-Id: <20210709051728.170203-16-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, Fabiano Rosas Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Fabiano Rosas ../target/ppc/mmu-hash32.c: In function 'ppc_hash32_bat_lookup': ../target/ppc/mmu-hash32.c:204:13: error: 'BATu' undeclared (first use in this function); 204 | BATu = &BATut[i]; | ^~~~ | BATut ../target/ppc/mmu-hash32.c:205:13: error: 'BATl' undeclared (first use in this function); 205 | BATl = &BATlt[i]; | ^~~~ | BATlt ../target/ppc/mmu-hash32.c:206:13: error: 'BEPIu' undeclared (first use in this function) 206 | BEPIu = *BATu & BATU32_BEPIU; | ^~~~~ ../target/ppc/mmu-hash32.c:206:29: error: 'BATU32_BEPIU' undeclared (first use in this function); 206 | BEPIu = *BATu & BATU32_BEPIU; | ^~~~~~~~~~~~ | BATU32_BEPI ../target/ppc/mmu-hash32.c:207:13: error: 'BEPIl' undeclared (first use in this function) 207 | BEPIl = *BATu & BATU32_BEPIL; | ^~~~~ ../target/ppc/mmu-hash32.c:207:29: error: 'BATU32_BEPIL' undeclared (first use in this function); 207 | BEPIl = *BATu & BATU32_BEPIL; | ^~~~~~~~~~~~ | BATU32_BEPI ../target/ppc/mmu-hash32.c:208:13: error: 'bl' undeclared (first use in this function) 208 | bl = (*BATu & 0x00001FFC) << 15; | ^~ Fixes: 9813279664 ("target-ppc: Disentangle BAT code for 32-bit hash MMUs") Signed-off-by: Fabiano Rosas Message-Id: <20210702215235.1941771-4-farosas@linux.ibm.com> Signed-off-by: David Gibson --- target/ppc/mmu-hash32.c | 5 ++++- target/ppc/mmu-hash32.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c index 6a07c345e4..4edd5ffe14 100644 --- a/target/ppc/mmu-hash32.c +++ b/target/ppc/mmu-hash32.c @@ -27,7 +27,7 @@ #include "mmu-hash32.h" #include "exec/log.h" -/* #define DEBUG_BAT */ +/* #define DEBUG_BATS */ #ifdef DEBUG_BATS # define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__) @@ -199,6 +199,9 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea, /* No hit */ #if defined(DEBUG_BATS) if (qemu_log_enabled()) { + target_ulong *BATu, *BATl; + target_ulong BEPIl, BEPIu, bl; + LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", ea); for (i = 0; i < 4; i++) { BATu = &BATut[i]; diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h index 8694eccabd..c9f584b8ee 100644 --- a/target/ppc/mmu-hash32.h +++ b/target/ppc/mmu-hash32.h @@ -22,6 +22,8 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, * Block Address Translation (BAT) definitions */ +#define BATU32_BEPIU 0xf0000000 +#define BATU32_BEPIL 0x0ffe0000 #define BATU32_BEPI 0xfffe0000 #define BATU32_BL 0x00001ffc #define BATU32_VS 0x00000002 From patchwork Fri Jul 9 05:17:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366735 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.8 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 BEF0CC07E99 for ; Fri, 9 Jul 2021 05:30:48 +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 6F3E76141E for ; Fri, 9 Jul 2021 05:30:48 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6F3E76141E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:46472 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j67-0002ij-CF for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:30:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35286) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itn-0001Jo-9n; Fri, 09 Jul 2021 01:18:03 -0400 Received: from ozlabs.org ([2401:3900:2:1::2]:56127) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1ith-00020K-Bq; Fri, 09 Jul 2021 01:18:03 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd6QGwz9t0G; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=Q0yuzRZG/zT44FIlhMaxwYZWoXjCktM633Qoxq67Dtg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JPz3kXSlOWnMA0ucIk3FALtiIqyVmCCu7r3QwEPA+/NJUfMp6JlBKRIdsiw0YSUey 1/a6Bo75nRsd6M3kbmF4iQ2SbGgDgX1qg/g7DY8W1eCNbNVw7V5/d5j6V3LrV6zM5n /9BVGBiq1KACd/TbTjw1OfW6NONqdhFjiHbe1gjg= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 16/33] target/ppc: fix address translation bug for radix mmus Date: Fri, 9 Jul 2021 15:17:11 +1000 Message-Id: <20210709051728.170203-17-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, Richard Henderson , qemu-devel@nongnu.org, qemu-ppc@nongnu.org, =?utf-8?q?C=C3=A9dric_Le_Goater?= , David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: "Bruno Larsen (billionai)" This commit attempts to fix a technical hiccup first mentioned by Richard Henderson in https://lists.nongnu.org/archive/html/qemu-devel/2021-05/msg06247.html To sumarize the hiccup here, when radix-style mmus are translating an address, they might need to call a second level of translation, with hypervisor privileges. However, the way it was being done up until this point meant that the second level translation had the same privileges as the first level. It could lead to a bug in address translation when running KVM inside a TCG guest, but this bug was never experienced by users, so this isn't as much a bug fix as it is a correctness cleanup. This patch attempts that cleanup by making radix64_*_xlate functions receive the mmu_idx, and passing one with the correct permission for the second level translation. The mmuidx macros added by this patch are only correct for non-bookE mmus, because BookE style set the IS and DS bits inverted and there might be other subtle differences. However, there doesn't seem to be BookE cpus that have radix-style mmus, so we left a comment there to document the issue, in case a machine does have that and was missed. As part of this cleanup, we now need to send the correct mmmu_idx when calling get_phys_page_debug, otherwise we might not be able to see the memory that the CPU could Suggested-by: Richard Henderson Signed-off-by: Bruno Larsen (billionai) Reviewed-by: Richard Henderson Reviewed-by: Cédric Le Goater Tested-by: Cédric Le Goater Message-Id: <20210628133610.1143-2-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson --- target/ppc/mmu-book3s-v3.h | 13 +++++++++++++ target/ppc/mmu-radix64.c | 37 +++++++++++++++++++++---------------- target/ppc/mmu-radix64.h | 2 +- target/ppc/mmu_helper.c | 8 +++++--- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h index a1326df969..c89d0bccfd 100644 --- a/target/ppc/mmu-book3s-v3.h +++ b/target/ppc/mmu-book3s-v3.h @@ -47,6 +47,19 @@ struct prtb_entry { uint64_t prtbe0, prtbe1; }; +/* + * These correspond to the mmu_idx values computed in + * hreg_compute_hflags_value. See the tables therein + * + * They are here because some bits are inverted for BookE MMUs + * not necessarily because they only work for BookS. However, + * we only needed to change BookS MMUs, we left the functions + * here to avoid other possible bugs for untested MMUs + */ +static inline bool mmuidx_pr(int idx) { return !(idx & 1); } +static inline bool mmuidx_real(int idx) { return idx & 2; } +static inline bool mmuidx_hv(int idx) { return idx & 4; } + #ifdef TARGET_PPC64 static inline bool ppc64_use_proc_tbl(PowerPCCPU *cpu) diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index cbd404bfa4..5b0e62e676 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -155,7 +155,7 @@ static void ppc_radix64_raise_hsi(PowerPCCPU *cpu, MMUAccessType access_type, static bool ppc_radix64_check_prot(PowerPCCPU *cpu, MMUAccessType access_type, uint64_t pte, int *fault_cause, int *prot, - bool partition_scoped) + int mmu_idx, bool partition_scoped) { CPUPPCState *env = &cpu->env; int need_prot; @@ -173,7 +173,8 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, MMUAccessType access_type, /* Determine permissions allowed by Encoded Access Authority */ if (!partition_scoped && (pte & R_PTE_EAA_PRIV) && msr_pr) { *prot = 0; - } else if (msr_pr || (pte & R_PTE_EAA_PRIV) || partition_scoped) { + } else if (mmuidx_pr(mmu_idx) || (pte & R_PTE_EAA_PRIV) || + partition_scoped) { *prot = ppc_radix64_get_prot_eaa(pte); } else { /* !msr_pr && !(pte & R_PTE_EAA_PRIV) && !partition_scoped */ *prot = ppc_radix64_get_prot_eaa(pte); @@ -299,7 +300,7 @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu, ppc_v3_pate_t pate, hwaddr *h_raddr, int *h_prot, int *h_page_size, bool pde_addr, - bool guest_visible) + int mmu_idx, bool guest_visible) { int fault_cause = 0; hwaddr pte_addr; @@ -310,7 +311,8 @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu, if (ppc_radix64_walk_tree(CPU(cpu)->as, g_raddr, pate.dw0 & PRTBE_R_RPDB, pate.dw0 & PRTBE_R_RPDS, h_raddr, h_page_size, &pte, &fault_cause, &pte_addr) || - ppc_radix64_check_prot(cpu, access_type, pte, &fault_cause, h_prot, true)) { + ppc_radix64_check_prot(cpu, access_type, pte, + &fault_cause, h_prot, mmu_idx, true)) { if (pde_addr) { /* address being translated was that of a guest pde */ fault_cause |= DSISR_PRTABLE_FAULT; } @@ -332,7 +334,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, vaddr eaddr, uint64_t pid, ppc_v3_pate_t pate, hwaddr *g_raddr, int *g_prot, int *g_page_size, - bool guest_visible) + int mmu_idx, bool guest_visible) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -367,7 +369,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, prtbe_addr, pate, &h_raddr, &h_prot, &h_page_size, true, - guest_visible); + /* mmu_idx is 5 because we're translating from hypervisor scope */ + 5, guest_visible); if (ret) { return ret; } @@ -407,7 +410,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, pte_addr, pate, &h_raddr, &h_prot, &h_page_size, true, - guest_visible); + /* mmu_idx is 5 because we're translating from hypervisor scope */ + 5, guest_visible); if (ret) { return ret; } @@ -431,7 +435,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, *g_raddr = (rpn & ~mask) | (eaddr & mask); } - if (ppc_radix64_check_prot(cpu, access_type, pte, &fault_cause, g_prot, false)) { + if (ppc_radix64_check_prot(cpu, access_type, pte, &fault_cause, + g_prot, mmu_idx, false)) { /* Access denied due to protection */ if (guest_visible) { ppc_radix64_raise_si(cpu, access_type, eaddr, fault_cause); @@ -464,7 +469,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, * +-------------+----------------+---------------+ */ bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, - hwaddr *raddr, int *psizep, int *protp, + hwaddr *raddr, int *psizep, int *protp, int mmu_idx, bool guest_visible) { CPUPPCState *env = &cpu->env; @@ -474,17 +479,17 @@ bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, hwaddr g_raddr; bool relocation; - assert(!(msr_hv && cpu->vhyp)); + assert(!(mmuidx_hv(mmu_idx) && cpu->vhyp)); - relocation = (access_type == MMU_INST_FETCH ? msr_ir : msr_dr); + relocation = !mmuidx_real(mmu_idx); /* HV or virtual hypervisor Real Mode Access */ - if (!relocation && (msr_hv || cpu->vhyp)) { + if (!relocation && (mmuidx_hv(mmu_idx) || cpu->vhyp)) { /* In real mode top 4 effective addr bits (mostly) ignored */ *raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL; /* In HV mode, add HRMOR if top EA bit is clear */ - if (msr_hv || !env->has_hv_mode) { + if (mmuidx_hv(mmu_idx) || !env->has_hv_mode) { if (!(eaddr >> 63)) { *raddr |= env->spr[SPR_HRMOR]; } @@ -546,7 +551,7 @@ bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, if (relocation) { int ret = ppc_radix64_process_scoped_xlate(cpu, access_type, eaddr, pid, pate, &g_raddr, &prot, - &psize, guest_visible); + &psize, mmu_idx, guest_visible); if (ret) { return false; } @@ -564,13 +569,13 @@ bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, * quadrants 1 or 2. Translates a guest real address to a host * real address. */ - if (lpid || !msr_hv) { + if (lpid || !mmuidx_hv(mmu_idx)) { int ret; ret = ppc_radix64_partition_scoped_xlate(cpu, access_type, eaddr, g_raddr, pate, raddr, &prot, &psize, false, - guest_visible); + mmu_idx, guest_visible); if (ret) { return false; } diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h index 6b13b89b64..b70357cf34 100644 --- a/target/ppc/mmu-radix64.h +++ b/target/ppc/mmu-radix64.h @@ -45,7 +45,7 @@ #ifdef TARGET_PPC64 bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, - hwaddr *raddr, int *psizep, int *protp, + hwaddr *raddr, int *psizep, int *protp, int mmu_idx, bool guest_visible); static inline int ppc_radix64_get_prot_eaa(uint64_t pte) diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 945ac41d42..46b4afce54 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -2900,7 +2900,7 @@ static bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, case POWERPC_MMU_3_00: if (ppc64_v3_radix(cpu)) { return ppc_radix64_xlate(cpu, eaddr, access_type, - raddrp, psizep, protp, guest_visible); + raddrp, psizep, protp, mmu_idx, guest_visible); } /* fall through */ case POWERPC_MMU_64B: @@ -2933,8 +2933,10 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) * try an MMU_DATA_LOAD, we may not be able to read instructions * mapped by code TLBs, so we also try a MMU_INST_FETCH. */ - if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p, 0, false) || - ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p, 0, false)) { + if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p, + cpu_mmu_index(&cpu->env, false), false) || + ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p, + cpu_mmu_index(&cpu->env, true), false)) { return raddr & TARGET_PAGE_MASK; } return -1; From patchwork Fri Jul 9 05:17:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366739 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.8 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 C53A2C07E99 for ; Fri, 9 Jul 2021 05:32:16 +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 6EDD16141E for ; Fri, 9 Jul 2021 05:32:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6EDD16141E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:52368 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j7X-0006qr-GT for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:32:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35266) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itl-0001Eg-2z; Fri, 09 Jul 2021 01:18:01 -0400 Received: from ozlabs.org ([203.11.71.1]:36813) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iti-00020q-Sw; Fri, 09 Jul 2021 01:18:00 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf0DCmz9t2b; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=dt8QWSKUXhXi3hxKjqNx/02uIHryLZDde/rSs0c2ub8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eWE63xwA4Bfl2XA+ljkTBHpixuSOInG/OMRpX/Zi+OAybmrQ8hDeVyCeI2DPlJ4PS f2WZXI//cXUDIMqeXdCWTAvxz08bb8b/8Zz9ZW9FiOBMSZxgYdpanh5GJCjDJL6kXQ TB/8jI2tJhGW9fcOw+HH3v4W7EMTR514hZQEpcUA= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 17/33] target/ppc: changed ppc_hash64_xlate to use mmu_idx Date: Fri, 9 Jul 2021 15:17:12 +1000 Message-Id: <20210709051728.170203-18-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, Richard Henderson , qemu-devel@nongnu.org, qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: "Bruno Larsen (billionai)" Changed hash64 address translation to use the supplied mmu_idx instead of using the one stored in the msr, for parity purposes (other book3s MMUs already use it). Signed-off-by: Bruno Larsen (billionai) Reviewed-by: Richard Henderson Message-Id: <20210628133610.1143-4-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson --- target/ppc/mmu-hash64.c | 43 ++++++++++++++++++++--------------------- target/ppc/mmu-hash64.h | 2 +- target/ppc/mmu_helper.c | 2 +- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index c1b98a97e9..19832c4b46 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -366,10 +366,9 @@ static inline int ppc_hash64_pte_noexec_guard(PowerPCCPU *cpu, } /* Check Basic Storage Protection */ -static int ppc_hash64_pte_prot(PowerPCCPU *cpu, +static int ppc_hash64_pte_prot(int mmu_idx, ppc_slb_t *slb, ppc_hash_pte64_t pte) { - CPUPPCState *env = &cpu->env; unsigned pp, key; /* * Some pp bit combinations have undefined behaviour, so default @@ -377,7 +376,7 @@ static int ppc_hash64_pte_prot(PowerPCCPU *cpu, */ int prot = 0; - key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP) + key = !!(mmuidx_pr(mmu_idx) ? (slb->vsid & SLB_VSID_KP) : (slb->vsid & SLB_VSID_KS)); pp = (pte.pte1 & HPTE64_R_PP) | ((pte.pte1 & HPTE64_R_PP0) >> 61); @@ -744,17 +743,17 @@ static bool ppc_hash64_use_vrma(CPUPPCState *env) } } -static void ppc_hash64_set_isi(CPUState *cs, uint64_t error_code) +static void ppc_hash64_set_isi(CPUState *cs, int mmu_idx, uint64_t error_code) { CPUPPCState *env = &POWERPC_CPU(cs)->env; bool vpm; - if (msr_ir) { + if (!mmuidx_real(mmu_idx)) { vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM1); } else { vpm = ppc_hash64_use_vrma(env); } - if (vpm && !msr_hv) { + if (vpm && !mmuidx_hv(mmu_idx)) { cs->exception_index = POWERPC_EXCP_HISI; } else { cs->exception_index = POWERPC_EXCP_ISI; @@ -762,17 +761,17 @@ static void ppc_hash64_set_isi(CPUState *cs, uint64_t error_code) env->error_code = error_code; } -static void ppc_hash64_set_dsi(CPUState *cs, uint64_t dar, uint64_t dsisr) +static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, uint64_t dar, uint64_t dsisr) { CPUPPCState *env = &POWERPC_CPU(cs)->env; bool vpm; - if (msr_dr) { + if (!mmuidx_real(mmu_idx)) { vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM1); } else { vpm = ppc_hash64_use_vrma(env); } - if (vpm && !msr_hv) { + if (vpm && !mmuidx_hv(mmu_idx)) { cs->exception_index = POWERPC_EXCP_HDSI; env->spr[SPR_HDAR] = dar; env->spr[SPR_HDSISR] = dsisr; @@ -874,7 +873,7 @@ static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb) } bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, - hwaddr *raddrp, int *psizep, int *protp, + hwaddr *raddrp, int *psizep, int *protp, int mmu_idx, bool guest_visible) { CPUState *cs = CPU(cpu); @@ -897,7 +896,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, */ /* 1. Handle real mode accesses */ - if (access_type == MMU_INST_FETCH ? !msr_ir : !msr_dr) { + if (mmuidx_real(mmu_idx)) { /* * Translation is supposedly "off", but in real mode the top 4 * effective address bits are (mostly) ignored @@ -909,7 +908,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, * In virtual hypervisor mode, there's nothing to do: * EA == GPA == qemu guest address */ - } else if (msr_hv || !env->has_hv_mode) { + } else if (mmuidx_hv(mmu_idx) || !env->has_hv_mode) { /* In HV mode, add HRMOR if top EA bit is clear */ if (!(eaddr >> 63)) { raddr |= env->spr[SPR_HRMOR]; @@ -937,13 +936,13 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, } switch (access_type) { case MMU_INST_FETCH: - ppc_hash64_set_isi(cs, SRR1_PROTFAULT); + ppc_hash64_set_isi(cs, mmu_idx, SRR1_PROTFAULT); break; case MMU_DATA_LOAD: - ppc_hash64_set_dsi(cs, eaddr, DSISR_PROTFAULT); + ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_PROTFAULT); break; case MMU_DATA_STORE: - ppc_hash64_set_dsi(cs, eaddr, + ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_PROTFAULT | DSISR_ISSTORE); break; default: @@ -996,7 +995,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, /* 3. Check for segment level no-execute violation */ if (access_type == MMU_INST_FETCH && (slb->vsid & SLB_VSID_N)) { if (guest_visible) { - ppc_hash64_set_isi(cs, SRR1_NOEXEC_GUARD); + ppc_hash64_set_isi(cs, mmu_idx, SRR1_NOEXEC_GUARD); } return false; } @@ -1009,13 +1008,13 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, } switch (access_type) { case MMU_INST_FETCH: - ppc_hash64_set_isi(cs, SRR1_NOPTE); + ppc_hash64_set_isi(cs, mmu_idx, SRR1_NOPTE); break; case MMU_DATA_LOAD: - ppc_hash64_set_dsi(cs, eaddr, DSISR_NOPTE); + ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_NOPTE); break; case MMU_DATA_STORE: - ppc_hash64_set_dsi(cs, eaddr, DSISR_NOPTE | DSISR_ISSTORE); + ppc_hash64_set_dsi(cs, mmu_idx, eaddr, DSISR_NOPTE | DSISR_ISSTORE); break; default: g_assert_not_reached(); @@ -1028,7 +1027,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, /* 5. Check access permissions */ exec_prot = ppc_hash64_pte_noexec_guard(cpu, pte); - pp_prot = ppc_hash64_pte_prot(cpu, slb, pte); + pp_prot = ppc_hash64_pte_prot(mmu_idx, slb, pte); amr_prot = ppc_hash64_amr_prot(cpu, pte); prot = exec_prot & pp_prot & amr_prot; @@ -1049,7 +1048,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, if (PAGE_EXEC & ~amr_prot) { srr1 |= SRR1_IAMR; /* Access violates virt pg class key prot */ } - ppc_hash64_set_isi(cs, srr1); + ppc_hash64_set_isi(cs, mmu_idx, srr1); } else { int dsisr = 0; if (need_prot & ~pp_prot) { @@ -1061,7 +1060,7 @@ bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, if (need_prot & ~amr_prot) { dsisr |= DSISR_AMR; } - ppc_hash64_set_dsi(cs, eaddr, dsisr); + ppc_hash64_set_dsi(cs, mmu_idx, eaddr, dsisr); } return false; } diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h index 9f338e1fe9..c5b2f97ff7 100644 --- a/target/ppc/mmu-hash64.h +++ b/target/ppc/mmu-hash64.h @@ -8,7 +8,7 @@ void dump_slb(PowerPCCPU *cpu); int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot, target_ulong esid, target_ulong vsid); bool ppc_hash64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, - hwaddr *raddrp, int *psizep, int *protp, + hwaddr *raddrp, int *psizep, int *protp, int mmu_idx, bool guest_visible); void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong pte_index, diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 46b4afce54..819ee27b62 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -2908,7 +2908,7 @@ static bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, case POWERPC_MMU_2_06: case POWERPC_MMU_2_07: return ppc_hash64_xlate(cpu, eaddr, access_type, - raddrp, psizep, protp, guest_visible); + raddrp, psizep, protp, mmu_idx, guest_visible); #endif case POWERPC_MMU_32B: From patchwork Fri Jul 9 05:17:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366733 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.8 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 DED32C07E99 for ; Fri, 9 Jul 2021 05:29:55 +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 7E1656141E for ; Fri, 9 Jul 2021 05:29:55 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7E1656141E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:43500 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j5G-0000Qx-J8 for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:29:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35240) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itj-0001BG-RP; Fri, 09 Jul 2021 01:17:59 -0400 Received: from bilbo.ozlabs.org ([2401:3900:2:1::2]:36297 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1ith-00020W-Nu; Fri, 09 Jul 2021 01:17:59 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHd6tm7z9t0T; Fri, 9 Jul 2021 15:17:33 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807853; bh=wWfJI//czSxg62ocsBCXtYJdbIEfRt97bicAmBKhoto=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZZjrQRKsMNAy4I5Vzb3skpZ3WHaeXpoBJ9sGXrFWtkACQHtj1pgwypusF1u12N/w1 l1IsZoxwj63boUuXHc7xZsCyNiNGND69eEtBACMMH4M5x1SNnmd+i/kxqjOCO169ME 7Qpcc9UekWD8u9J8sC9z6j608KENE/GEnhWTOXu8= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 18/33] target/ppc: introduce mmu-books.h Date: Fri, 9 Jul 2021 15:17:13 +1000 Message-Id: <20210709051728.170203-19-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: "Bruno Larsen (billionai)" Intrudoce a header common to all BookS MMUs, that can hold code that is common to hash32 and book3s-v3 MMUs. Suggested-by: David Gibson Signed-off-by: Bruno Larsen (billionai) Message-Id: <20210706150316.21005-2-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson --- target/ppc/mmu-book3s-v3.h | 14 +------------- target/ppc/mmu-books.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 target/ppc/mmu-books.h diff --git a/target/ppc/mmu-book3s-v3.h b/target/ppc/mmu-book3s-v3.h index c89d0bccfd..d6d5ed8f8e 100644 --- a/target/ppc/mmu-book3s-v3.h +++ b/target/ppc/mmu-book3s-v3.h @@ -21,6 +21,7 @@ #define PPC_MMU_BOOK3S_V3_H #include "mmu-hash64.h" +#include "mmu-books.h" #ifndef CONFIG_USER_ONLY @@ -47,19 +48,6 @@ struct prtb_entry { uint64_t prtbe0, prtbe1; }; -/* - * These correspond to the mmu_idx values computed in - * hreg_compute_hflags_value. See the tables therein - * - * They are here because some bits are inverted for BookE MMUs - * not necessarily because they only work for BookS. However, - * we only needed to change BookS MMUs, we left the functions - * here to avoid other possible bugs for untested MMUs - */ -static inline bool mmuidx_pr(int idx) { return !(idx & 1); } -static inline bool mmuidx_real(int idx) { return idx & 2; } -static inline bool mmuidx_hv(int idx) { return idx & 4; } - #ifdef TARGET_PPC64 static inline bool ppc64_use_proc_tbl(PowerPCCPU *cpu) diff --git a/target/ppc/mmu-books.h b/target/ppc/mmu-books.h new file mode 100644 index 0000000000..0d12551867 --- /dev/null +++ b/target/ppc/mmu-books.h @@ -0,0 +1,30 @@ +/* + * PowerPC BookS emulation generic mmu definitions for qemu. + * + * Copyright (c) 2021 Instituto de Pesquisas Eldorado (eldorado.org.br) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef PPC_MMU_BOOKS_H +#define PPC_MMU_BOOKS_H + +/* + * These correspond to the mmu_idx values computed in + * hreg_compute_hflags_value. See the tables therein + */ +static inline bool mmuidx_pr(int idx) { return !(idx & 1); } +static inline bool mmuidx_real(int idx) { return idx & 2; } +static inline bool mmuidx_hv(int idx) { return idx & 4; } +#endif /* PPC_MMU_BOOKS_H */ From patchwork Fri Jul 9 05:17:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366761 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.8 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 7D261C07E99 for ; Fri, 9 Jul 2021 05:43:48 +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 0ED4161447 for ; Fri, 9 Jul 2021 05:43:48 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0ED4161447 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:49014 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jIh-0006tZ-3z for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:43:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35276) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itl-0001GK-Vo; Fri, 09 Jul 2021 01:18:02 -0400 Received: from bilbo.ozlabs.org ([2401:3900:2:1::2]:47947 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iti-000210-UE; Fri, 09 Jul 2021 01:18:01 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf0Z2fz9t0Z; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=ezsD5meFiNROogxj/DEs8MK7R1EMrmcwNZLRqTlUPl4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AYfJOWcopSIHZ+YJyNY+Ot8ywNfQEd0YffAZViENG+ii+yxSjQQq1RbKyHF6bqAlZ A9qdqrYb6fgTlyRPpDO2fYauivZS3OIMXCj++/BaWfljweJP7jZb+yGd8bH7FbPAI1 ZJr+7pcCwq/mcZIH3I2kmtEKegPQhQp9Okbjwnwc= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 19/33] target/ppc: change ppc_hash32_xlate to use mmu_idx Date: Fri, 9 Jul 2021 15:17:14 +1000 Message-Id: <20210709051728.170203-20-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: "Bruno Larsen (billionai)" Changed hash32 address translation to use the supplied mmu_idx, instead of using what was stored in the msr, for parity purposes (radix64 already uses that) and for conceptual correctness, all the relevant functions should always use the supplied mmu_idx, as there are no guarantees that the mmu_idx stored in the CPU variable will not desync. Signed-off-by: Bruno Larsen (billionai) Reviewed-by: David Gibson Message-Id: <20210706150316.21005-3-bruno.larsen@eldorado.org.br> Signed-off-by: David Gibson --- target/ppc/mmu-hash32.c | 40 +++++++++++++++++++--------------------- target/ppc/mmu-hash32.h | 2 +- target/ppc/mmu_helper.c | 2 +- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c index 4edd5ffe14..3957aab2dc 100644 --- a/target/ppc/mmu-hash32.c +++ b/target/ppc/mmu-hash32.c @@ -25,6 +25,7 @@ #include "kvm_ppc.h" #include "internal.h" #include "mmu-hash32.h" +#include "mmu-books.h" #include "exec/log.h" /* #define DEBUG_BATS */ @@ -86,25 +87,22 @@ static int ppc_hash32_pp_prot(int key, int pp, int nx) return prot; } -static int ppc_hash32_pte_prot(PowerPCCPU *cpu, +static int ppc_hash32_pte_prot(int mmu_idx, target_ulong sr, ppc_hash_pte32_t pte) { - CPUPPCState *env = &cpu->env; unsigned pp, key; - key = !!(msr_pr ? (sr & SR32_KP) : (sr & SR32_KS)); + key = !!(mmuidx_pr(mmu_idx) ? (sr & SR32_KP) : (sr & SR32_KS)); pp = pte.pte1 & HPTE32_R_PP; return ppc_hash32_pp_prot(key, pp, !!(sr & SR32_NX)); } -static target_ulong hash32_bat_size(PowerPCCPU *cpu, +static target_ulong hash32_bat_size(int mmu_idx, target_ulong batu, target_ulong batl) { - CPUPPCState *env = &cpu->env; - - if ((msr_pr && !(batu & BATU32_VP)) - || (!msr_pr && !(batu & BATU32_VS))) { + if ((mmuidx_pr(mmu_idx) && !(batu & BATU32_VP)) + || (!mmuidx_pr(mmu_idx) && !(batu & BATU32_VS))) { return 0; } @@ -137,14 +135,13 @@ static target_ulong hash32_bat_601_size(PowerPCCPU *cpu, return BATU32_BEPI & ~((batl & BATL32_601_BL) << 17); } -static int hash32_bat_601_prot(PowerPCCPU *cpu, +static int hash32_bat_601_prot(int mmu_idx, target_ulong batu, target_ulong batl) { - CPUPPCState *env = &cpu->env; int key, pp; pp = batu & BATU32_601_PP; - if (msr_pr == 0) { + if (mmuidx_pr(mmu_idx) == 0) { key = !!(batu & BATU32_601_KS); } else { key = !!(batu & BATU32_601_KP); @@ -153,7 +150,8 @@ static int hash32_bat_601_prot(PowerPCCPU *cpu, } static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea, - MMUAccessType access_type, int *prot) + MMUAccessType access_type, int *prot, + int mmu_idx) { CPUPPCState *env = &cpu->env; target_ulong *BATlt, *BATut; @@ -177,7 +175,7 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea, if (unlikely(env->mmu_model == POWERPC_MMU_601)) { mask = hash32_bat_601_size(cpu, batu, batl); } else { - mask = hash32_bat_size(cpu, batu, batl); + mask = hash32_bat_size(mmu_idx, batu, batl); } LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__, @@ -187,7 +185,7 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea, hwaddr raddr = (batl & mask) | (ea & ~mask); if (unlikely(env->mmu_model == POWERPC_MMU_601)) { - *prot = hash32_bat_601_prot(cpu, batu, batl); + *prot = hash32_bat_601_prot(mmu_idx, batu, batl); } else { *prot = hash32_bat_prot(cpu, batu, batl); } @@ -224,12 +222,12 @@ static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea, static bool ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr, target_ulong eaddr, MMUAccessType access_type, - hwaddr *raddr, int *prot, + hwaddr *raddr, int *prot, int mmu_idx, bool guest_visible) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; - int key = !!(msr_pr ? (sr & SR32_KP) : (sr & SR32_KS)); + int key = !!(mmuidx_pr(mmu_idx) ? (sr & SR32_KP) : (sr & SR32_KS)); qemu_log_mask(CPU_LOG_MMU, "direct store...\n"); @@ -428,7 +426,7 @@ static hwaddr ppc_hash32_pte_raddr(target_ulong sr, ppc_hash_pte32_t pte, } bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, - hwaddr *raddrp, int *psizep, int *protp, + hwaddr *raddrp, int *psizep, int *protp, int mmu_idx, bool guest_visible) { CPUState *cs = CPU(cpu); @@ -444,7 +442,7 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, *psizep = TARGET_PAGE_BITS; /* 1. Handle real mode accesses */ - if (access_type == MMU_INST_FETCH ? !msr_ir : !msr_dr) { + if (mmuidx_real(mmu_idx)) { /* Translation is off */ *raddrp = eaddr; *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC; @@ -455,7 +453,7 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, /* 2. Check Block Address Translation entries (BATs) */ if (env->nb_BATs != 0) { - raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, protp); + raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, protp, mmu_idx); if (raddr != -1) { if (need_prot & ~*protp) { if (guest_visible) { @@ -486,7 +484,7 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, /* 4. Handle direct store segments */ if (sr & SR32_T) { return ppc_hash32_direct_store(cpu, sr, eaddr, access_type, - raddrp, protp, guest_visible); + raddrp, protp, mmu_idx, guest_visible); } /* 5. Check for segment level no-execute violation */ @@ -523,7 +521,7 @@ bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, /* 7. Check access permissions */ - prot = ppc_hash32_pte_prot(cpu, sr, pte); + prot = ppc_hash32_pte_prot(mmu_idx, sr, pte); if (need_prot & ~prot) { /* Access right violation */ diff --git a/target/ppc/mmu-hash32.h b/target/ppc/mmu-hash32.h index c9f584b8ee..3892b693d6 100644 --- a/target/ppc/mmu-hash32.h +++ b/target/ppc/mmu-hash32.h @@ -5,7 +5,7 @@ hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash); bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, - hwaddr *raddrp, int *psizep, int *protp, + hwaddr *raddrp, int *psizep, int *protp, int mmu_idx, bool guest_visible); /* diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 819ee27b62..47e9f9529e 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -2914,7 +2914,7 @@ static bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, case POWERPC_MMU_32B: case POWERPC_MMU_601: return ppc_hash32_xlate(cpu, eaddr, access_type, - raddrp, psizep, protp, guest_visible); + raddrp, psizep, protp, mmu_idx, guest_visible); default: return ppc_jumbo_xlate(cpu, eaddr, access_type, raddrp, From patchwork Fri Jul 9 05:17:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366757 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=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,NORMAL_HTTP_TO_IP,NUMERIC_HTTP_ADDR,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,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 E68FBC07E99 for ; Fri, 9 Jul 2021 05:40:46 +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 5AC0A61441 for ; Fri, 9 Jul 2021 05:40:46 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5AC0A61441 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:44412 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jFl-0003Sz-G7 for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:40:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35488) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuI-0002Ww-RD; Fri, 09 Jul 2021 01:18:34 -0400 Received: from bilbo.ozlabs.org ([2401:3900:2:1::2]:58999 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iu3-00022T-TD; Fri, 09 Jul 2021 01:18:34 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf15qcz9t2g; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=HXlRLY7mfbz0uWexkkuex1BkxxPvEq3aD6tZhpecmcw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=O+1WVxwwQD1Ho6snd3PzW7WM3up5sP+QhIwQD9YbFfGAyynZyz5gLxlaBKaKlDCR3 cQAxfE+1aaZsghf6SY5wAEYJnLtyLjoQq181iwG0D9mHOQIj+gcJnM0K2jOWHbrOTn WaNNLdfbuJUyV4e6eN8WakyUA5wti1d+RshmaAD8= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 20/33] roms/u-boot: Bump ppce500 u-boot to v2021.07 to add eTSEC support Date: Fri, 9 Jul 2021 15:17:15 +1000 Message-Id: <20210709051728.170203-21-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, Bin Meng , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Bin Meng Update the QEMU shipped u-boot.e500 image built from U-Boot mainline v2021.07 release, which added eTSEC support to the QEMU ppce500 target, via the following U-Boot series: http://patchwork.ozlabs.org/project/uboot/list/?series=233875&state=* The cross-compilation toolchain used to build the U-Boot image is: https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/10.1.0/x86_64-gcc-10.1.0-nolibc-powerpc-linux.tar.xz Signed-off-by: Bin Meng Signed-off-by: David Gibson --- pc-bios/u-boot.e500 | Bin 406920 -> 421720 bytes roms/u-boot | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/u-boot.e500 b/pc-bios/u-boot.e500 index d2e29f81d648e4fa7e010ab7c44f2d22154094aa..8e635c8a5c9e53469710be27aa0c5e5a4045c2cd 100644 GIT binary patch delta 117630 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 F{{aRmAFu!b delta 102979 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 J^cErV{{aOP5+MKp diff --git a/roms/u-boot b/roms/u-boot index b46dd116ce..840658b093 160000 --- a/roms/u-boot +++ b/roms/u-boot @@ -1 +1 @@ -Subproject commit b46dd116ce03e235f2a7d4843c6278e1da44b5e1 +Subproject commit 840658b093976390e9537724f802281c9c8439f5 From patchwork Fri Jul 9 05:17:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366727 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.8 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 50268C07E99 for ; Fri, 9 Jul 2021 05:28:21 +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 0315F61002 for ; Fri, 9 Jul 2021 05:28:20 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0315F61002 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:37708 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j3k-0004kJ-6E for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:28:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35282) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itm-0001He-KU; Fri, 09 Jul 2021 01:18:02 -0400 Received: from ozlabs.org ([203.11.71.1]:49343) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itk-00022g-3q; Fri, 09 Jul 2021 01:18:02 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf270Gz9t4b; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=XMcyrR+d9xk9axuD4XJcT+E2fMa7254X/u6MOfcxdxE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UXgJgwNWYYOdke3DSeQzidP7Uie4cS6vk1og1Za0R2SGGd5dNE/xl3EqWj8YlWRM4 mlV7VOVkwV+nTd1ZjTMqrV2Mx1Dyeb62f+PnoLyWu1fIrOc7K7Nl1gHhzdU5mT8SoJ 4yRd9QqG0vg7bJVaGr5a42kbo7Swo6OTVPKDcw7c= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 21/33] docs/system: ppc: Update ppce500 documentation with eTSEC support Date: Fri, 9 Jul 2021 15:17:16 +1000 Message-Id: <20210709051728.170203-22-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, Bin Meng , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Bin Meng This adds eTSEC support to the PowerPC `ppce500` machine documentation. Signed-off-by: Bin Meng Signed-off-by: David Gibson --- docs/system/ppc/ppce500.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/system/ppc/ppce500.rst b/docs/system/ppc/ppce500.rst index 7a815c1881..afc58f60f5 100644 --- a/docs/system/ppc/ppce500.rst +++ b/docs/system/ppc/ppce500.rst @@ -19,6 +19,7 @@ The ``ppce500`` machine supports the following devices: * Power-off functionality via one GPIO pin * 1 Freescale MPC8xxx PCI host controller * VirtIO devices via PCI bus +* 1 Freescale Enhanced Triple Speed Ethernet controller (eTSEC) Hardware configuration information ---------------------------------- @@ -121,7 +122,7 @@ To boot the 32-bit Linux kernel: Running U-Boot -------------- -U-Boot mainline v2021.04 release is tested at the time of writing. To build a +U-Boot mainline v2021.07 release is tested at the time of writing. To build a U-Boot mainline bootloader that can be booted by the ``ppce500`` machine, use the qemu-ppce500_defconfig with similar commands as described above for Linux: @@ -154,3 +155,10 @@ interface at PCI address 0.1.0, but we can switch that to an e1000 NIC by: -display none -serial stdio \ -bios u-boot \ -nic tap,ifname=tap0,script=no,downscript=no,model=e1000 + +The QEMU ``ppce500`` machine can also dynamically instantiate an eTSEC device +if “-device eTSEC” is given to QEMU: + +.. code-block:: bash + + -netdev tap,ifname=tap0,script=no,downscript=no,id=net0 -device eTSEC,netdev=net0 From patchwork Fri Jul 9 05:17:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366743 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=-20.1 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,SPF_HELO_NONE,SPF_PASS,URIBL_BLACK, 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 EB3A7C07E99 for ; Fri, 9 Jul 2021 05:34:01 +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 513E061442 for ; Fri, 9 Jul 2021 05:34:01 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 513E061442 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:57472 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j9E-0001o7-8P for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:34:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35400) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuB-0002K4-EB; Fri, 09 Jul 2021 01:18:27 -0400 Received: from ozlabs.org ([2401:3900:2:1::2]:46199) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iu4-00022q-RE; Fri, 09 Jul 2021 01:18:26 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf2bySz9t54; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=k+SjY7N+vRIvuLJ58PF040X0VFJCAjFCVMxXdc3Q+hM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=o55WkjC78NLQgXyEDBpBS1v6lMCsj7sWmQmhUY8iRC0oVidL9EetPhlJVPTYikxIZ MxkmON2KPTrMrGJy0Tl3ZrVXyu4JbId45u4aRCbdkqrZ2GbaVJUmWqQ9i2xFpqbXwJ yY9Cg/LQQDtj0mGt0uOF8fkOgpA6bMNUkQ6RP1Uc= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 22/33] spapr: Implement Open Firmware client interface Date: Fri, 9 Jul 2021 15:17:17 +1000 Message-Id: <20210709051728.170203-23-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Alexey Kardashevskiy The PAPR platform describes an OS environment that's presented by a combination of a hypervisor and firmware. The features it specifies require collaboration between the firmware and the hypervisor. Since the beginning, the runtime component of the firmware (RTAS) has been implemented as a 20 byte shim which simply forwards it to a hypercall implemented in qemu. The boot time firmware component is SLOF - but a build that's specific to qemu, and has always needed to be updated in sync with it. Even though we've managed to limit the amount of runtime communication we need between qemu and SLOF, there's some, and it has become increasingly awkward to handle as we've implemented new features. This implements a boot time OF client interface (CI) which is enabled by a new "x-vof" pseries machine option (stands for "Virtual Open Firmware). When enabled, QEMU implements the custom H_OF_CLIENT hcall which implements Open Firmware Client Interface (OF CI). This allows using a smaller stateless firmware which does not have to manage the device tree. The new "vof.bin" firmware image is included with source code under pc-bios/. It also includes RTAS blob. This implements a handful of CI methods just to get -kernel/-initrd working. In particular, this implements the device tree fetching and simple memory allocator - "claim" (an OF CI memory allocator) and updates "/memory@0/available" to report the client about available memory. This implements changing some device tree properties which we know how to deal with, the rest is ignored. To allow changes, this skips fdt_pack() when x-vof=on as not packing the blob leaves some room for appending. In absence of SLOF, this assigns phandles to device tree nodes to make device tree traversing work. When x-vof=on, this adds "/chosen" every time QEMU (re)builds a tree. This adds basic instances support which are managed by a hash map ihandle -> [phandle]. Before the guest started, the used memory is: 0..e60 - the initial firmware 8000..10000 - stack 400000.. - kernel 3ea0000.. - initramdisk This OF CI does not implement "interpret". Unlike SLOF, this does not format uninitialized nvram. Instead, this includes a disk image with pre-formatted nvram. With this basic support, this can only boot into kernel directly. However this is just enough for the petitboot kernel and initradmdisk to boot from any possible source. Note this requires reasonably recent guest kernel with: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=df5be5be8735 The immediate benefit is much faster booting time which especially crucial with fully emulated early CPU bring up environments. Also this may come handy when/if GRUB-in-the-userspace sees light of the day. This separates VOF and sPAPR in a hope that VOF bits may be reused by other POWERPC boards which do not support pSeries. This assumes potential support for booting from QEMU backends such as blockdev or netdev without devices/drivers used. Signed-off-by: Alexey Kardashevskiy Message-Id: <20210625055155.2252896-1-aik@ozlabs.ru> Reviewed-by: BALATON Zoltan [dwg: Adjusted some includes which broke compile in some more obscure compilation setups] Signed-off-by: David Gibson --- MAINTAINERS | 12 + hw/ppc/Kconfig | 4 + hw/ppc/meson.build | 3 + hw/ppc/spapr.c | 67 ++- hw/ppc/spapr_hcall.c | 25 +- hw/ppc/spapr_vof.c | 153 ++++++ hw/ppc/trace-events | 24 + hw/ppc/vof.c | 1049 +++++++++++++++++++++++++++++++++++++++ include/hw/ppc/spapr.h | 19 +- include/hw/ppc/vof.h | 58 +++ pc-bios/README | 4 + pc-bios/vof-nvram.bin | Bin 0 -> 16384 bytes pc-bios/vof.bin | Bin 0 -> 3784 bytes pc-bios/vof/Makefile | 23 + pc-bios/vof/bootmem.c | 14 + pc-bios/vof/ci.c | 91 ++++ pc-bios/vof/entry.S | 49 ++ pc-bios/vof/libc.c | 92 ++++ pc-bios/vof/main.c | 21 + pc-bios/vof/vof.h | 43 ++ pc-bios/vof/vof.lds | 48 ++ tests/qtest/rtas-test.c | 15 +- 22 files changed, 1801 insertions(+), 13 deletions(-) create mode 100644 hw/ppc/spapr_vof.c create mode 100644 hw/ppc/vof.c create mode 100644 include/hw/ppc/vof.h create mode 100644 pc-bios/vof-nvram.bin create mode 100755 pc-bios/vof.bin create mode 100644 pc-bios/vof/Makefile create mode 100644 pc-bios/vof/bootmem.c create mode 100644 pc-bios/vof/ci.c create mode 100644 pc-bios/vof/entry.S create mode 100644 pc-bios/vof/libc.c create mode 100644 pc-bios/vof/main.c create mode 100644 pc-bios/vof/vof.h create mode 100644 pc-bios/vof/vof.lds diff --git a/MAINTAINERS b/MAINTAINERS index 684142e12e..ce122eeced 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1360,6 +1360,18 @@ F: hw/pci-host/mv64361.c F: hw/pci-host/mv643xx.h F: include/hw/pci-host/mv64361.h +Virtual Open Firmware (VOF) +M: Alexey Kardashevskiy +M: David Gibson +M: Greg Kurz +L: qemu-ppc@nongnu.org +S: Maintained +F: hw/ppc/spapr_vof* +F: hw/ppc/vof* +F: include/hw/ppc/vof* +F: pc-bios/vof/* +F: pc-bios/vof* + RISC-V Machines --------------- OpenTitan diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig index 66e0b15d9e..67630f80e1 100644 --- a/hw/ppc/Kconfig +++ b/hw/ppc/Kconfig @@ -13,6 +13,7 @@ config PSERIES select MSI_NONBROKEN select FDT_PPC select CHRP_NVRAM + select VOF config SPAPR_RNG bool @@ -144,3 +145,6 @@ config FW_CFG_PPC config FDT_PPC bool + +config VOF + bool diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build index 597d974dd4..aa4c8e6a2e 100644 --- a/hw/ppc/meson.build +++ b/hw/ppc/meson.build @@ -84,4 +84,7 @@ ppc_ss.add(when: 'CONFIG_VIRTEX', if_true: files('virtex_ml507.c')) # Pegasos2 ppc_ss.add(when: 'CONFIG_PEGASOS2', if_true: files('pegasos2.c')) +ppc_ss.add(when: 'CONFIG_VOF', if_true: files('vof.c')) +ppc_ss.add(when: ['CONFIG_VOF', 'CONFIG_PSERIES'], if_true: files('spapr_vof.c')) + hw_arch += {'ppc': ppc_ss} diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 9e19c57032..e9b6d0f587 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -101,6 +101,7 @@ #define FDT_MAX_ADDR 0x80000000 /* FDT must stay below that */ #define FW_MAX_SIZE 0x400000 #define FW_FILE_NAME "slof.bin" +#define FW_FILE_NAME_VOF "vof.bin" #define FW_OVERHEAD 0x2800000 #define KERNEL_LOAD_ADDR FW_MAX_SIZE @@ -1643,22 +1644,37 @@ static void spapr_machine_reset(MachineState *machine) fdt_addr = MIN(spapr->rma_size, FDT_MAX_ADDR) - FDT_MAX_SIZE; fdt = spapr_build_fdt(spapr, true, FDT_MAX_SIZE); + if (spapr->vof) { + target_ulong stack_ptr = 0; - rc = fdt_pack(fdt); + spapr_vof_reset(spapr, fdt, &stack_ptr, &error_fatal); - /* Should only fail if we've built a corrupted tree */ - assert(rc == 0); + spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, + stack_ptr, spapr->initrd_base, + spapr->initrd_size); + /* VOF is 32bit BE so enforce MSR here */ + first_ppc_cpu->env.msr &= ~((1ULL << MSR_SF) | (1ULL << MSR_LE)); + /* + * Do not pack the FDT as the client may change properties. + * VOF client does not expect the FDT so we do not load it to the VM. + */ + } else { + rc = fdt_pack(fdt); + /* Should only fail if we've built a corrupted tree */ + assert(rc == 0); - /* Load the fdt */ + spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, + 0, fdt_addr, 0); + cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); + } qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); - cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); + g_free(spapr->fdt_blob); spapr->fdt_size = fdt_totalsize(fdt); spapr->fdt_initial_size = spapr->fdt_size; spapr->fdt_blob = fdt; /* Set up the entry state */ - spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, 0, fdt_addr, 0); first_ppc_cpu->env.gpr[5] = 0; spapr->fwnmi_system_reset_addr = -1; @@ -2661,7 +2677,8 @@ static void spapr_machine_init(MachineState *machine) SpaprMachineState *spapr = SPAPR_MACHINE(machine); SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); MachineClass *mc = MACHINE_GET_CLASS(machine); - const char *bios_name = machine->firmware ?: FW_FILE_NAME; + const char *bios_default = spapr->vof ? FW_FILE_NAME_VOF : FW_FILE_NAME; + const char *bios_name = machine->firmware ?: bios_default; const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; PCIHostState *phb; @@ -3018,6 +3035,10 @@ static void spapr_machine_init(MachineState *machine) } qemu_cond_init(&spapr->fwnmi_machine_check_interlock_cond); + if (spapr->vof) { + spapr->vof->fw_size = fw_size; /* for claim() on itself */ + spapr_register_hypercall(KVMPPC_H_VOF_CLIENT, spapr_h_vof_client); + } } #define DEFAULT_KVM_TYPE "auto" @@ -3208,6 +3229,28 @@ static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp) } } +static bool spapr_get_vof(Object *obj, Error **errp) +{ + SpaprMachineState *spapr = SPAPR_MACHINE(obj); + + return spapr->vof != NULL; +} + +static void spapr_set_vof(Object *obj, bool value, Error **errp) +{ + SpaprMachineState *spapr = SPAPR_MACHINE(obj); + + if (spapr->vof) { + vof_cleanup(spapr->vof); + g_free(spapr->vof); + spapr->vof = NULL; + } + if (!value) { + return; + } + spapr->vof = g_malloc0(sizeof(*spapr->vof)); +} + static char *spapr_get_ic_mode(Object *obj, Error **errp) { SpaprMachineState *spapr = SPAPR_MACHINE(obj); @@ -3333,6 +3376,11 @@ static void spapr_instance_init(Object *obj) stringify(KERNEL_LOAD_ADDR) " for -kernel is the default"); spapr->kernel_addr = KERNEL_LOAD_ADDR; + + object_property_add_bool(obj, "x-vof", spapr_get_vof, spapr_set_vof); + object_property_set_description(obj, "x-vof", + "Enable Virtual Open Firmware (experimental)"); + /* The machine class defines the default interrupt controller mode */ spapr->irq = smc->irq; object_property_add_str(obj, "ic-mode", spapr_get_ic_mode, @@ -4496,6 +4544,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); + VofMachineIfClass *vmc = VOF_MACHINE_CLASS(oc); mc->desc = "pSeries Logical Partition (PAPR compliant)"; mc->ignore_boot_device_suffixes = true; @@ -4584,6 +4633,9 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) smc->smp_threads_vsmt = true; smc->nr_xirqs = SPAPR_NR_XIRQS; xfc->match_nvt = spapr_match_nvt; + vmc->client_architecture_support = spapr_vof_client_architecture_support; + vmc->quiesce = spapr_vof_quiesce; + vmc->setprop = spapr_vof_setprop; } static const TypeInfo spapr_machine_info = { @@ -4603,6 +4655,7 @@ static const TypeInfo spapr_machine_info = { { TYPE_XICS_FABRIC }, { TYPE_INTERRUPT_STATS_PROVIDER }, { TYPE_XIVE_FABRIC }, + { TYPE_VOF_MACHINE_IF }, { } }, }; diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index f25014afda..03fc191599 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1080,7 +1080,7 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu, SpaprOptionVector *ov1_guest, *ov5_guest; bool guest_radix; bool raw_mode_supported = false; - bool guest_xive; + bool guest_xive, reset_fdt = false; CPUState *cs; void *fdt; uint32_t max_compat = spapr->max_compat_pvr; @@ -1233,8 +1233,8 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu, spapr_setup_hpt(spapr); } - fdt = spapr_build_fdt(spapr, false, fdt_bufsize); - + reset_fdt = spapr->vof != NULL; + fdt = spapr_build_fdt(spapr, reset_fdt, fdt_bufsize); g_free(spapr->fdt_blob); spapr->fdt_size = fdt_totalsize(fdt); spapr->fdt_initial_size = spapr->fdt_size; @@ -1277,6 +1277,25 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, return ret; } +target_ulong spapr_vof_client_architecture_support(MachineState *ms, + CPUState *cs, + target_ulong ovec_addr) +{ + SpaprMachineState *spapr = SPAPR_MACHINE(ms); + + target_ulong ret = do_client_architecture_support(POWERPC_CPU(cs), spapr, + ovec_addr, FDT_MAX_SIZE); + + /* + * This adds stdout and generates phandles for boottime and CAS FDTs. + * It is alright to update the FDT here as do_client_architecture_support() + * does not pack it. + */ + spapr_vof_client_dt_finalize(spapr, spapr->fdt_blob); + + return ret; +} + static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong opcode, diff --git a/hw/ppc/spapr_vof.c b/hw/ppc/spapr_vof.c new file mode 100644 index 0000000000..131a03fec0 --- /dev/null +++ b/hw/ppc/spapr_vof.c @@ -0,0 +1,153 @@ +/* + * SPAPR machine hooks to Virtual Open Firmware, + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qapi/error.h" +#include "hw/ppc/spapr.h" +#include "hw/ppc/spapr_vio.h" +#include "hw/ppc/fdt.h" +#include "hw/ppc/vof.h" +#include "sysemu/sysemu.h" +#include "qom/qom-qobject.h" +#include "trace.h" + +target_ulong spapr_h_vof_client(PowerPCCPU *cpu, SpaprMachineState *spapr, + target_ulong opcode, target_ulong *_args) +{ + int ret = vof_client_call(MACHINE(spapr), spapr->vof, spapr->fdt_blob, + ppc64_phys_to_real(_args[0])); + + if (ret) { + return H_PARAMETER; + } + return H_SUCCESS; +} + +void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt) +{ + char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); + int chosen; + + vof_build_dt(fdt, spapr->vof); + + _FDT(chosen = fdt_path_offset(fdt, "/chosen")); + _FDT(fdt_setprop_string(fdt, chosen, "bootargs", + spapr->vof->bootargs ? : "")); + + /* + * SLOF-less setup requires an open instance of stdout for early + * kernel printk. By now all phandles are settled so we can open + * the default serial console. + */ + if (stdout_path) { + _FDT(vof_client_open_store(fdt, spapr->vof, "/chosen", "stdout", + stdout_path)); + } +} + +void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, + target_ulong *stack_ptr, Error **errp) +{ + Vof *vof = spapr->vof; + + vof_init(vof, spapr->rma_size, errp); + + *stack_ptr = vof_claim(vof, 0, VOF_STACK_SIZE, VOF_STACK_SIZE); + if (*stack_ptr == -1) { + error_setg(errp, "Memory allocation for stack failed"); + return; + } + /* Stack grows downwards plus reserve space for the minimum stack frame */ + *stack_ptr += VOF_STACK_SIZE - 0x20; + + if (spapr->kernel_size && + vof_claim(vof, spapr->kernel_addr, spapr->kernel_size, 0) == -1) { + error_setg(errp, "Memory for kernel is in use"); + return; + } + + if (spapr->initrd_size && + vof_claim(vof, spapr->initrd_base, spapr->initrd_size, 0) == -1) { + error_setg(errp, "Memory for initramdisk is in use"); + return; + } + + spapr_vof_client_dt_finalize(spapr, fdt); + + /* + * At this point the expected allocation map is: + * + * 0..c38 - the initial firmware + * 8000..10000 - stack + * 400000.. - kernel + * 3ea0000.. - initramdisk + * + * We skip writing FDT as nothing expects it; OF client interface is + * going to be used for reading the device tree. + */ +} + +void spapr_vof_quiesce(MachineState *ms) +{ + SpaprMachineState *spapr = SPAPR_MACHINE(ms); + + spapr->fdt_size = fdt_totalsize(spapr->fdt_blob); + spapr->fdt_initial_size = spapr->fdt_size; +} + +bool spapr_vof_setprop(MachineState *ms, const char *path, const char *propname, + void *val, int vallen) +{ + SpaprMachineState *spapr = SPAPR_MACHINE(ms); + + /* + * We only allow changing properties which we know how to update in QEMU + * OR + * the ones which we know that they need to survive during "quiesce". + */ + + if (strcmp(path, "/rtas") == 0) { + if (strcmp(propname, "linux,rtas-base") == 0 || + strcmp(propname, "linux,rtas-entry") == 0) { + /* These need to survive quiesce so let them store in the FDT */ + return true; + } + } + + if (strcmp(path, "/chosen") == 0) { + if (strcmp(propname, "bootargs") == 0) { + Vof *vof = spapr->vof; + + g_free(vof->bootargs); + vof->bootargs = g_strndup(val, vallen); + return true; + } + if (strcmp(propname, "linux,initrd-start") == 0) { + if (vallen == sizeof(uint32_t)) { + spapr->initrd_base = ldl_be_p(val); + return true; + } + if (vallen == sizeof(uint64_t)) { + spapr->initrd_base = ldq_be_p(val); + return true; + } + return false; + } + if (strcmp(propname, "linux,initrd-end") == 0) { + if (vallen == sizeof(uint32_t)) { + spapr->initrd_size = ldl_be_p(val) - spapr->initrd_base; + return true; + } + if (vallen == sizeof(uint64_t)) { + spapr->initrd_size = ldq_be_p(val) - spapr->initrd_base; + return true; + } + return false; + } + } + + return true; +} diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index 0ba3e40353..6e90a01072 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -71,6 +71,30 @@ spapr_rtas_ibm_configure_connector_invalid(uint32_t index) "DRC index: 0x%"PRIx3 spapr_vio_h_reg_crq(uint64_t reg, uint64_t queue_addr, uint64_t queue_len) "CRQ for dev 0x%" PRIx64 " registered at 0x%" PRIx64 "/0x%" PRIx64 spapr_vio_free_crq(uint32_t reg) "CRQ for dev 0x%" PRIx32 " freed" +# vof.c +vof_error_str_truncated(const char *s, int len) "%s truncated to %d" +vof_error_param(const char *method, int nargscheck, int nretcheck, int nargs, int nret) "%s takes/returns %d/%d, not %d/%d" +vof_error_unknown_service(const char *service, int nargs, int nret) "\"%s\" args=%d rets=%d" +vof_error_unknown_method(const char *method) "\"%s\"" +vof_error_unknown_ihandle_close(uint32_t ih) "ih=0x%x" +vof_error_unknown_path(const char *path) "\"%s\"" +vof_error_write(uint32_t ih) "ih=0x%x" +vof_finddevice(const char *path, uint32_t ph) "\"%s\" => ph=0x%x" +vof_claim(uint32_t virt, uint32_t size, uint32_t align, uint32_t ret) "virt=0x%x size=0x%x align=0x%x => 0x%x" +vof_release(uint32_t virt, uint32_t size, uint32_t ret) "virt=0x%x size=0x%x => 0x%x" +vof_method(uint32_t ihandle, const char *method, uint32_t param, uint32_t ret, uint32_t ret2) "ih=0x%x \"%s\"(0x%x) => 0x%x 0x%x" +vof_getprop(uint32_t ph, const char *prop, uint32_t ret, const char *val) "ph=0x%x \"%s\" => len=%d [%s]" +vof_getproplen(uint32_t ph, const char *prop, uint32_t ret) "ph=0x%x \"%s\" => len=%d" +vof_setprop(uint32_t ph, const char *prop, const char *val, uint32_t vallen, uint32_t ret) "ph=0x%x \"%s\" [%s] len=%d => ret=%d" +vof_open(const char *path, uint32_t ph, uint32_t ih) "%s ph=0x%x => ih=0x%x" +vof_interpret(const char *cmd, uint32_t param1, uint32_t param2, uint32_t ret, uint32_t ret2) "[%s] 0x%x 0x%x => 0x%x 0x%x" +vof_package_to_path(uint32_t ph, const char *tmp, uint32_t ret) "ph=0x%x => %s len=%d" +vof_instance_to_path(uint32_t ih, uint32_t ph, const char *tmp, uint32_t ret) "ih=0x%x ph=0x%x => %s len=%d" +vof_instance_to_package(uint32_t ih, uint32_t ph) "ih=0x%x => ph=0x%x" +vof_write(uint32_t ih, unsigned cb, const char *msg) "ih=0x%x [%u] \"%s\"" +vof_avail(uint64_t start, uint64_t end, uint64_t size) "0x%"PRIx64"..0x%"PRIx64" size=0x%"PRIx64 +vof_claimed(uint64_t start, uint64_t end, uint64_t size) "0x%"PRIx64"..0x%"PRIx64" size=0x%"PRIx64 + # ppc.c ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "adjusted from 0x%"PRIx64" to 0x%"PRIx64", diff %"PRId64" (%"PRId64"s)" diff --git a/hw/ppc/vof.c b/hw/ppc/vof.c new file mode 100644 index 0000000000..47c86e394e --- /dev/null +++ b/hw/ppc/vof.c @@ -0,0 +1,1049 @@ +/* + * QEMU PowerPC Virtual Open Firmware. + * + * This implements client interface from OpenFirmware IEEE1275 on the QEMU + * side to leave only a very basic firmware in the VM. + * + * Copyright (c) 2021 IBM Corporation. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/timer.h" +#include "qemu/range.h" +#include "qemu/units.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "exec/ram_addr.h" +#include "exec/address-spaces.h" +#include "hw/ppc/vof.h" +#include "hw/ppc/fdt.h" +#include "sysemu/runstate.h" +#include "qom/qom-qobject.h" +#include "trace.h" + +#include + +/* + * OF 1275 "nextprop" description suggests is it 32 bytes max but + * LoPAPR defines "ibm,query-interrupt-source-number" which is 33 chars long. + */ +#define OF_PROPNAME_LEN_MAX 64 + +#define VOF_MAX_PATH 256 +#define VOF_MAX_SETPROPLEN 2048 +#define VOF_MAX_METHODLEN 256 +#define VOF_MAX_FORTHCODE 256 +#define VOF_VTY_BUF_SIZE 256 + +typedef struct { + uint64_t start; + uint64_t size; +} OfClaimed; + +typedef struct { + char *path; /* the path used to open the instance */ + uint32_t phandle; +} OfInstance; + +static int readstr(hwaddr pa, char *buf, int size) +{ + if (VOF_MEM_READ(pa, buf, size) != MEMTX_OK) { + return -1; + } + if (strnlen(buf, size) == size) { + buf[size - 1] = '\0'; + trace_vof_error_str_truncated(buf, size); + return -1; + } + return 0; +} + +static bool cmpservice(const char *s, unsigned nargs, unsigned nret, + const char *s1, unsigned nargscheck, unsigned nretcheck) +{ + if (strcmp(s, s1)) { + return false; + } + if ((nargscheck && (nargs != nargscheck)) || + (nretcheck && (nret != nretcheck))) { + trace_vof_error_param(s, nargscheck, nretcheck, nargs, nret); + return false; + } + + return true; +} + +static void prop_format(char *tval, int tlen, const void *prop, int len) +{ + int i; + const unsigned char *c; + char *t; + const char bin[] = "..."; + + for (i = 0, c = prop; i < len; ++i, ++c) { + if (*c == '\0' && i == len - 1) { + strncpy(tval, prop, tlen - 1); + return; + } + if (*c < 0x20 || *c >= 0x80) { + break; + } + } + + for (i = 0, c = prop, t = tval; i < len; ++i, ++c) { + if (t >= tval + tlen - sizeof(bin) - 1 - 2 - 1) { + strcpy(t, bin); + return; + } + if (i && i % 4 == 0 && i != len - 1) { + strcat(t, " "); + ++t; + } + t += sprintf(t, "%02X", *c & 0xFF); + } +} + +static int get_path(const void *fdt, int offset, char *buf, int len) +{ + int ret; + + ret = fdt_get_path(fdt, offset, buf, len - 1); + if (ret < 0) { + return ret; + } + + buf[len - 1] = '\0'; + + return strlen(buf) + 1; +} + +static int phandle_to_path(const void *fdt, uint32_t ph, char *buf, int len) +{ + int ret; + + ret = fdt_node_offset_by_phandle(fdt, ph); + if (ret < 0) { + return ret; + } + + return get_path(fdt, ret, buf, len); +} + +static int path_offset(const void *fdt, const char *path) +{ + g_autofree char *p = NULL; + char *at; + + /* + * https://www.devicetree.org/open-firmware/bindings/ppc/release/ppc-2_1.html#HDR16 + * + * "Conversion from numeric representation to text representation shall use + * the lower case forms of the hexadecimal digits in the range a..f, + * suppressing leading zeros". + */ + at = strchr(path, '@'); + if (!at) { + return fdt_path_offset(fdt, path); + } + + p = g_strdup(path); + for (at = at - path + p + 1; *at; ++at) { + *at = tolower(*at); + } + return fdt_path_offset(fdt, p); +} + +static uint32_t vof_finddevice(const void *fdt, uint32_t nodeaddr) +{ + char fullnode[VOF_MAX_PATH]; + uint32_t ret = -1; + int offset; + + if (readstr(nodeaddr, fullnode, sizeof(fullnode))) { + return (uint32_t) ret; + } + + offset = path_offset(fdt, fullnode); + if (offset >= 0) { + ret = fdt_get_phandle(fdt, offset); + } + trace_vof_finddevice(fullnode, ret); + return (uint32_t) ret; +} + +static const void *getprop(const void *fdt, int nodeoff, const char *propname, + int *proplen, bool *write0) +{ + const char *unit, *prop; + const void *ret = fdt_getprop(fdt, nodeoff, propname, proplen); + + if (ret) { + if (write0) { + *write0 = false; + } + return ret; + } + + if (strcmp(propname, "name")) { + return NULL; + } + /* + * We return a value for "name" from path if queried but property does not + * exist. @proplen does not include the unit part in this case. + */ + prop = fdt_get_name(fdt, nodeoff, proplen); + if (!prop) { + *proplen = 0; + return NULL; + } + + unit = memchr(prop, '@', *proplen); + if (unit) { + *proplen = unit - prop; + } + *proplen += 1; + + /* + * Since it might be cut at "@" and there will be no trailing zero + * in the prop buffer, tell the caller to write zero at the end. + */ + if (write0) { + *write0 = true; + } + return prop; +} + +static uint32_t vof_getprop(const void *fdt, uint32_t nodeph, uint32_t pname, + uint32_t valaddr, uint32_t vallen) +{ + char propname[OF_PROPNAME_LEN_MAX + 1]; + uint32_t ret = 0; + int proplen = 0; + const void *prop; + char trval[64] = ""; + int nodeoff = fdt_node_offset_by_phandle(fdt, nodeph); + bool write0; + + if (nodeoff < 0) { + return -1; + } + if (readstr(pname, propname, sizeof(propname))) { + return -1; + } + prop = getprop(fdt, nodeoff, propname, &proplen, &write0); + if (prop) { + const char zero = 0; + int cb = MIN(proplen, vallen); + + if (VOF_MEM_WRITE(valaddr, prop, cb) != MEMTX_OK || + /* if that was "name" with a unit address, overwrite '@' with '0' */ + (write0 && + cb == proplen && + VOF_MEM_WRITE(valaddr + cb - 1, &zero, 1) != MEMTX_OK)) { + ret = -1; + } else { + /* + * OF1275 says: + * "Size is either the actual size of the property, or -1 if name + * does not exist", hence returning proplen instead of cb. + */ + ret = proplen; + /* Do not format a value if tracepoint is silent, for performance */ + if (trace_event_get_state(TRACE_VOF_GETPROP) && + qemu_loglevel_mask(LOG_TRACE)) { + prop_format(trval, sizeof(trval), prop, ret); + } + } + } else { + ret = -1; + } + trace_vof_getprop(nodeph, propname, ret, trval); + + return ret; +} + +static uint32_t vof_getproplen(const void *fdt, uint32_t nodeph, uint32_t pname) +{ + char propname[OF_PROPNAME_LEN_MAX + 1]; + uint32_t ret = 0; + int proplen = 0; + const void *prop; + int nodeoff = fdt_node_offset_by_phandle(fdt, nodeph); + + if (nodeoff < 0) { + return -1; + } + if (readstr(pname, propname, sizeof(propname))) { + return -1; + } + prop = getprop(fdt, nodeoff, propname, &proplen, NULL); + if (prop) { + ret = proplen; + } else { + ret = -1; + } + trace_vof_getproplen(nodeph, propname, ret); + + return ret; +} + +static uint32_t vof_setprop(MachineState *ms, void *fdt, Vof *vof, + uint32_t nodeph, uint32_t pname, + uint32_t valaddr, uint32_t vallen) +{ + char propname[OF_PROPNAME_LEN_MAX + 1]; + uint32_t ret = -1; + int offset; + char trval[64] = ""; + char nodepath[VOF_MAX_PATH] = ""; + Object *vmo = object_dynamic_cast(OBJECT(ms), TYPE_VOF_MACHINE_IF); + g_autofree char *val = NULL; + + if (vallen > VOF_MAX_SETPROPLEN) { + goto trace_exit; + } + if (readstr(pname, propname, sizeof(propname))) { + goto trace_exit; + } + offset = fdt_node_offset_by_phandle(fdt, nodeph); + if (offset < 0) { + goto trace_exit; + } + ret = get_path(fdt, offset, nodepath, sizeof(nodepath)); + if (ret <= 0) { + goto trace_exit; + } + + val = g_malloc0(vallen); + if (VOF_MEM_READ(valaddr, val, vallen) != MEMTX_OK) { + goto trace_exit; + } + + if (vmo) { + VofMachineIfClass *vmc = VOF_MACHINE_GET_CLASS(vmo); + + if (vmc->setprop && + !vmc->setprop(ms, nodepath, propname, val, vallen)) { + goto trace_exit; + } + } + + ret = fdt_setprop(fdt, offset, propname, val, vallen); + if (ret) { + goto trace_exit; + } + + if (trace_event_get_state(TRACE_VOF_SETPROP) && + qemu_loglevel_mask(LOG_TRACE)) { + prop_format(trval, sizeof(trval), val, vallen); + } + ret = vallen; + +trace_exit: + trace_vof_setprop(nodeph, propname, trval, vallen, ret); + + return ret; +} + +static uint32_t vof_nextprop(const void *fdt, uint32_t phandle, + uint32_t prevaddr, uint32_t nameaddr) +{ + int offset, nodeoff = fdt_node_offset_by_phandle(fdt, phandle); + char prev[OF_PROPNAME_LEN_MAX + 1]; + const char *tmp; + + if (readstr(prevaddr, prev, sizeof(prev))) { + return -1; + } + + fdt_for_each_property_offset(offset, fdt, nodeoff) { + if (!fdt_getprop_by_offset(fdt, offset, &tmp, NULL)) { + return 0; + } + if (prev[0] == '\0' || strcmp(prev, tmp) == 0) { + if (prev[0] != '\0') { + offset = fdt_next_property_offset(fdt, offset); + if (offset < 0) { + return 0; + } + } + if (!fdt_getprop_by_offset(fdt, offset, &tmp, NULL)) { + return 0; + } + + if (VOF_MEM_WRITE(nameaddr, tmp, strlen(tmp) + 1) != MEMTX_OK) { + return -1; + } + return 1; + } + } + + return 0; +} + +static uint32_t vof_peer(const void *fdt, uint32_t phandle) +{ + int ret; + + if (phandle == 0) { + ret = fdt_path_offset(fdt, "/"); + } else { + ret = fdt_next_subnode(fdt, fdt_node_offset_by_phandle(fdt, phandle)); + } + + if (ret < 0) { + ret = 0; + } else { + ret = fdt_get_phandle(fdt, ret); + } + + return ret; +} + +static uint32_t vof_child(const void *fdt, uint32_t phandle) +{ + int ret = fdt_first_subnode(fdt, fdt_node_offset_by_phandle(fdt, phandle)); + + if (ret < 0) { + ret = 0; + } else { + ret = fdt_get_phandle(fdt, ret); + } + + return ret; +} + +static uint32_t vof_parent(const void *fdt, uint32_t phandle) +{ + int ret = fdt_parent_offset(fdt, fdt_node_offset_by_phandle(fdt, phandle)); + + if (ret < 0) { + ret = 0; + } else { + ret = fdt_get_phandle(fdt, ret); + } + + return ret; +} + +static uint32_t vof_do_open(void *fdt, Vof *vof, int offset, const char *path) +{ + uint32_t ret = -1; + OfInstance *inst = NULL; + + if (vof->of_instance_last == 0xFFFFFFFF) { + /* We do not recycle ihandles yet */ + goto trace_exit; + } + + inst = g_new0(OfInstance, 1); + inst->phandle = fdt_get_phandle(fdt, offset); + g_assert(inst->phandle); + ++vof->of_instance_last; + + inst->path = g_strdup(path); + g_hash_table_insert(vof->of_instances, + GINT_TO_POINTER(vof->of_instance_last), + inst); + ret = vof->of_instance_last; + +trace_exit: + trace_vof_open(path, inst ? inst->phandle : 0, ret); + + return ret; +} + +uint32_t vof_client_open_store(void *fdt, Vof *vof, const char *nodename, + const char *prop, const char *path) +{ + int node = fdt_path_offset(fdt, nodename); + int inst, offset; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) { + trace_vof_error_unknown_path(path); + return offset; + } + + inst = vof_do_open(fdt, vof, offset, path); + + return fdt_setprop_cell(fdt, node, prop, inst); +} + +static uint32_t vof_open(void *fdt, Vof *vof, uint32_t pathaddr) +{ + char path[VOF_MAX_PATH]; + int offset; + + if (readstr(pathaddr, path, sizeof(path))) { + return -1; + } + + offset = path_offset(fdt, path); + if (offset < 0) { + trace_vof_error_unknown_path(path); + return offset; + } + + return vof_do_open(fdt, vof, offset, path); +} + +static void vof_close(Vof *vof, uint32_t ihandle) +{ + if (!g_hash_table_remove(vof->of_instances, GINT_TO_POINTER(ihandle))) { + trace_vof_error_unknown_ihandle_close(ihandle); + } +} + +static uint32_t vof_instance_to_package(Vof *vof, uint32_t ihandle) +{ + gpointer instp = g_hash_table_lookup(vof->of_instances, + GINT_TO_POINTER(ihandle)); + uint32_t ret = -1; + + if (instp) { + ret = ((OfInstance *)instp)->phandle; + } + trace_vof_instance_to_package(ihandle, ret); + + return ret; +} + +static uint32_t vof_package_to_path(const void *fdt, uint32_t phandle, + uint32_t buf, uint32_t len) +{ + uint32_t ret = -1; + char tmp[VOF_MAX_PATH] = ""; + + ret = phandle_to_path(fdt, phandle, tmp, sizeof(tmp)); + if (ret > 0) { + if (VOF_MEM_WRITE(buf, tmp, ret) != MEMTX_OK) { + ret = -1; + } + } + + trace_vof_package_to_path(phandle, tmp, ret); + + return ret; +} + +static uint32_t vof_instance_to_path(void *fdt, Vof *vof, uint32_t ihandle, + uint32_t buf, uint32_t len) +{ + uint32_t ret = -1; + uint32_t phandle = vof_instance_to_package(vof, ihandle); + char tmp[VOF_MAX_PATH] = ""; + + if (phandle != -1) { + ret = phandle_to_path(fdt, phandle, tmp, sizeof(tmp)); + if (ret > 0) { + if (VOF_MEM_WRITE(buf, tmp, ret) != MEMTX_OK) { + ret = -1; + } + } + } + trace_vof_instance_to_path(ihandle, phandle, tmp, ret); + + return ret; +} + +static uint32_t vof_write(Vof *vof, uint32_t ihandle, uint32_t buf, + uint32_t len) +{ + char tmp[VOF_VTY_BUF_SIZE]; + unsigned cb; + OfInstance *inst = (OfInstance *) + g_hash_table_lookup(vof->of_instances, GINT_TO_POINTER(ihandle)); + + if (!inst) { + trace_vof_error_write(ihandle); + return -1; + } + + for ( ; len > 0; len -= cb) { + cb = MIN(len, sizeof(tmp) - 1); + if (VOF_MEM_READ(buf, tmp, cb) != MEMTX_OK) { + return -1; + } + + /* FIXME: there is no backend(s) yet so just call a trace */ + if (trace_event_get_state(TRACE_VOF_WRITE) && + qemu_loglevel_mask(LOG_TRACE)) { + tmp[cb] = '\0'; + trace_vof_write(ihandle, cb, tmp); + } + } + + return len; +} + +static void vof_claimed_dump(GArray *claimed) +{ + int i; + OfClaimed c; + + if (trace_event_get_state(TRACE_VOF_CLAIMED) && + qemu_loglevel_mask(LOG_TRACE)) { + + for (i = 0; i < claimed->len; ++i) { + c = g_array_index(claimed, OfClaimed, i); + trace_vof_claimed(c.start, c.start + c.size, c.size); + } + } +} + +static bool vof_claim_avail(GArray *claimed, uint64_t virt, uint64_t size) +{ + int i; + OfClaimed c; + + for (i = 0; i < claimed->len; ++i) { + c = g_array_index(claimed, OfClaimed, i); + if (ranges_overlap(c.start, c.size, virt, size)) { + return false; + } + } + + return true; +} + +static void vof_claim_add(GArray *claimed, uint64_t virt, uint64_t size) +{ + OfClaimed newclaim; + + newclaim.start = virt; + newclaim.size = size; + g_array_append_val(claimed, newclaim); +} + +static gint of_claimed_compare_func(gconstpointer a, gconstpointer b) +{ + return ((OfClaimed *)a)->start - ((OfClaimed *)b)->start; +} + +static void vof_dt_memory_available(void *fdt, GArray *claimed, uint64_t base) +{ + int i, n, offset, proplen = 0, sc, ac; + target_ulong mem0_end; + const uint8_t *mem0_reg; + g_autofree uint8_t *avail = NULL; + uint8_t *availcur; + + if (!fdt || !claimed) { + return; + } + + offset = fdt_path_offset(fdt, "/"); + _FDT(offset); + ac = fdt_address_cells(fdt, offset); + g_assert(ac == 1 || ac == 2); + sc = fdt_size_cells(fdt, offset); + g_assert(sc == 1 || sc == 2); + + offset = fdt_path_offset(fdt, "/memory@0"); + _FDT(offset); + + mem0_reg = fdt_getprop(fdt, offset, "reg", &proplen); + g_assert(mem0_reg && proplen == sizeof(uint32_t) * (ac + sc)); + if (sc == 2) { + mem0_end = be64_to_cpu(*(uint64_t *)(mem0_reg + sizeof(uint32_t) * ac)); + } else { + mem0_end = be32_to_cpu(*(uint32_t *)(mem0_reg + sizeof(uint32_t) * ac)); + } + + g_array_sort(claimed, of_claimed_compare_func); + vof_claimed_dump(claimed); + + /* + * VOF resides in the first page so we do not need to check if there is + * available memory before the first claimed block + */ + g_assert(claimed->len && (g_array_index(claimed, OfClaimed, 0).start == 0)); + + avail = g_malloc0(sizeof(uint32_t) * (ac + sc) * claimed->len); + for (i = 0, n = 0, availcur = avail; i < claimed->len; ++i) { + OfClaimed c = g_array_index(claimed, OfClaimed, i); + uint64_t start, size; + + start = c.start + c.size; + if (i < claimed->len - 1) { + OfClaimed cn = g_array_index(claimed, OfClaimed, i + 1); + + size = cn.start - start; + } else { + size = mem0_end - start; + } + + if (ac == 2) { + *(uint64_t *) availcur = cpu_to_be64(start); + } else { + *(uint32_t *) availcur = cpu_to_be32(start); + } + availcur += sizeof(uint32_t) * ac; + if (sc == 2) { + *(uint64_t *) availcur = cpu_to_be64(size); + } else { + *(uint32_t *) availcur = cpu_to_be32(size); + } + availcur += sizeof(uint32_t) * sc; + + if (size) { + trace_vof_avail(c.start + c.size, c.start + c.size + size, size); + ++n; + } + } + _FDT((fdt_setprop(fdt, offset, "available", avail, availcur - avail))); +} + +/* + * OF1275: + * "Allocates size bytes of memory. If align is zero, the allocated range + * begins at the virtual address virt. Otherwise, an aligned address is + * automatically chosen and the input argument virt is ignored". + * + * In other words, exactly one of @virt and @align is non-zero. + */ +uint64_t vof_claim(Vof *vof, uint64_t virt, uint64_t size, + uint64_t align) +{ + uint64_t ret; + + if (size == 0) { + ret = -1; + } else if (align == 0) { + if (!vof_claim_avail(vof->claimed, virt, size)) { + ret = -1; + } else { + ret = virt; + } + } else { + vof->claimed_base = QEMU_ALIGN_UP(vof->claimed_base, align); + while (1) { + if (vof->claimed_base >= vof->top_addr) { + error_report("Out of RMA memory for the OF client"); + return -1; + } + if (vof_claim_avail(vof->claimed, vof->claimed_base, size)) { + break; + } + vof->claimed_base += size; + } + ret = vof->claimed_base; + } + + if (ret != -1) { + vof->claimed_base = MAX(vof->claimed_base, ret + size); + vof_claim_add(vof->claimed, ret, size); + } + trace_vof_claim(virt, size, align, ret); + + return ret; +} + +static uint32_t vof_release(Vof *vof, uint64_t virt, uint64_t size) +{ + uint32_t ret = -1; + int i; + GArray *claimed = vof->claimed; + OfClaimed c; + + for (i = 0; i < claimed->len; ++i) { + c = g_array_index(claimed, OfClaimed, i); + if (c.start == virt && c.size == size) { + g_array_remove_index(claimed, i); + ret = 0; + break; + } + } + + trace_vof_release(virt, size, ret); + + return ret; +} + +static void vof_instantiate_rtas(Error **errp) +{ + error_setg(errp, "The firmware should have instantiated RTAS"); +} + +static uint32_t vof_call_method(MachineState *ms, Vof *vof, uint32_t methodaddr, + uint32_t ihandle, uint32_t param1, + uint32_t param2, uint32_t param3, + uint32_t param4, uint32_t *ret2) +{ + uint32_t ret = -1; + char method[VOF_MAX_METHODLEN] = ""; + OfInstance *inst; + + if (!ihandle) { + goto trace_exit; + } + + inst = (OfInstance *)g_hash_table_lookup(vof->of_instances, + GINT_TO_POINTER(ihandle)); + if (!inst) { + goto trace_exit; + } + + if (readstr(methodaddr, method, sizeof(method))) { + goto trace_exit; + } + + if (strcmp(inst->path, "/") == 0) { + if (strcmp(method, "ibm,client-architecture-support") == 0) { + Object *vmo = object_dynamic_cast(OBJECT(ms), TYPE_VOF_MACHINE_IF); + + if (vmo) { + VofMachineIfClass *vmc = VOF_MACHINE_GET_CLASS(vmo); + + g_assert(vmc->client_architecture_support); + ret = vmc->client_architecture_support(ms, first_cpu, param1); + } + + *ret2 = 0; + } + } else if (strcmp(inst->path, "/rtas") == 0) { + if (strcmp(method, "instantiate-rtas") == 0) { + vof_instantiate_rtas(&error_fatal); + ret = 0; + *ret2 = param1; /* rtas-base */ + } + } else { + trace_vof_error_unknown_method(method); + } + +trace_exit: + trace_vof_method(ihandle, method, param1, ret, *ret2); + + return ret; +} + +static uint32_t vof_call_interpret(uint32_t cmdaddr, uint32_t param1, + uint32_t param2, uint32_t *ret2) +{ + uint32_t ret = -1; + char cmd[VOF_MAX_FORTHCODE] = ""; + + /* No interpret implemented so just call a trace */ + readstr(cmdaddr, cmd, sizeof(cmd)); + trace_vof_interpret(cmd, param1, param2, ret, *ret2); + + return ret; +} + +static void vof_quiesce(MachineState *ms, void *fdt, Vof *vof) +{ + Object *vmo = object_dynamic_cast(OBJECT(ms), TYPE_VOF_MACHINE_IF); + /* After "quiesce", no change is expected to the FDT, pack FDT to ensure */ + int rc = fdt_pack(fdt); + + assert(rc == 0); + + if (vmo) { + VofMachineIfClass *vmc = VOF_MACHINE_GET_CLASS(vmo); + + if (vmc->quiesce) { + vmc->quiesce(ms); + } + } + + vof_claimed_dump(vof->claimed); +} + +static uint32_t vof_client_handle(MachineState *ms, void *fdt, Vof *vof, + const char *service, + uint32_t *args, unsigned nargs, + uint32_t *rets, unsigned nrets) +{ + uint32_t ret = 0; + + /* @nrets includes the value which this function returns */ +#define cmpserv(s, a, r) \ + cmpservice(service, nargs, nrets, (s), (a), (r)) + + if (cmpserv("finddevice", 1, 1)) { + ret = vof_finddevice(fdt, args[0]); + } else if (cmpserv("getprop", 4, 1)) { + ret = vof_getprop(fdt, args[0], args[1], args[2], args[3]); + } else if (cmpserv("getproplen", 2, 1)) { + ret = vof_getproplen(fdt, args[0], args[1]); + } else if (cmpserv("setprop", 4, 1)) { + ret = vof_setprop(ms, fdt, vof, args[0], args[1], args[2], args[3]); + } else if (cmpserv("nextprop", 3, 1)) { + ret = vof_nextprop(fdt, args[0], args[1], args[2]); + } else if (cmpserv("peer", 1, 1)) { + ret = vof_peer(fdt, args[0]); + } else if (cmpserv("child", 1, 1)) { + ret = vof_child(fdt, args[0]); + } else if (cmpserv("parent", 1, 1)) { + ret = vof_parent(fdt, args[0]); + } else if (cmpserv("open", 1, 1)) { + ret = vof_open(fdt, vof, args[0]); + } else if (cmpserv("close", 1, 0)) { + vof_close(vof, args[0]); + } else if (cmpserv("instance-to-package", 1, 1)) { + ret = vof_instance_to_package(vof, args[0]); + } else if (cmpserv("package-to-path", 3, 1)) { + ret = vof_package_to_path(fdt, args[0], args[1], args[2]); + } else if (cmpserv("instance-to-path", 3, 1)) { + ret = vof_instance_to_path(fdt, vof, args[0], args[1], args[2]); + } else if (cmpserv("write", 3, 1)) { + ret = vof_write(vof, args[0], args[1], args[2]); + } else if (cmpserv("claim", 3, 1)) { + ret = vof_claim(vof, args[0], args[1], args[2]); + if (ret != -1) { + vof_dt_memory_available(fdt, vof->claimed, vof->claimed_base); + } + } else if (cmpserv("release", 2, 0)) { + ret = vof_release(vof, args[0], args[1]); + if (ret != -1) { + vof_dt_memory_available(fdt, vof->claimed, vof->claimed_base); + } + } else if (cmpserv("call-method", 0, 0)) { + ret = vof_call_method(ms, vof, args[0], args[1], args[2], args[3], + args[4], args[5], rets); + } else if (cmpserv("interpret", 0, 0)) { + ret = vof_call_interpret(args[0], args[1], args[2], rets); + } else if (cmpserv("milliseconds", 0, 1)) { + ret = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); + } else if (cmpserv("quiesce", 0, 0)) { + vof_quiesce(ms, fdt, vof); + } else if (cmpserv("exit", 0, 0)) { + error_report("Stopped as the VM requested \"exit\""); + vm_stop(RUN_STATE_PAUSED); + } else { + trace_vof_error_unknown_service(service, nargs, nrets); + ret = -1; + } + + return ret; +} + +/* Defined as Big Endian */ +struct prom_args { + uint32_t service; + uint32_t nargs; + uint32_t nret; + uint32_t args[10]; +} QEMU_PACKED; + +int vof_client_call(MachineState *ms, Vof *vof, void *fdt, + target_ulong args_real) +{ + struct prom_args args_be; + uint32_t args[ARRAY_SIZE(args_be.args)]; + uint32_t rets[ARRAY_SIZE(args_be.args)] = { 0 }, ret; + char service[64]; + unsigned nargs, nret, i; + + if (VOF_MEM_READ(args_real, &args_be, sizeof(args_be)) != MEMTX_OK) { + return -EINVAL; + } + nargs = be32_to_cpu(args_be.nargs); + if (nargs >= ARRAY_SIZE(args_be.args)) { + return -EINVAL; + } + + if (VOF_MEM_READ(be32_to_cpu(args_be.service), service, sizeof(service)) != + MEMTX_OK) { + return -EINVAL; + } + if (strnlen(service, sizeof(service)) == sizeof(service)) { + /* Too long service name */ + return -EINVAL; + } + + for (i = 0; i < nargs; ++i) { + args[i] = be32_to_cpu(args_be.args[i]); + } + + nret = be32_to_cpu(args_be.nret); + ret = vof_client_handle(ms, fdt, vof, service, args, nargs, rets, nret); + if (!nret) { + return 0; + } + + args_be.args[nargs] = cpu_to_be32(ret); + for (i = 1; i < nret; ++i) { + args_be.args[nargs + i] = cpu_to_be32(rets[i - 1]); + } + + if (VOF_MEM_WRITE(args_real + offsetof(struct prom_args, args[nargs]), + args_be.args + nargs, sizeof(args_be.args[0]) * nret) != + MEMTX_OK) { + return -EINVAL; + } + + return 0; +} + +static void vof_instance_free(gpointer data) +{ + OfInstance *inst = (OfInstance *)data; + + g_free(inst->path); + g_free(inst); +} + +void vof_init(Vof *vof, uint64_t top_addr, Error **errp) +{ + vof_cleanup(vof); + + vof->of_instances = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, vof_instance_free); + vof->claimed = g_array_new(false, false, sizeof(OfClaimed)); + + /* Keep allocations in 32bit as CLI ABI can only return cells==32bit */ + vof->top_addr = MIN(top_addr, 4 * GiB); + if (vof_claim(vof, 0, vof->fw_size, 0) == -1) { + error_setg(errp, "Memory for firmware is in use"); + } +} + +void vof_cleanup(Vof *vof) +{ + if (vof->claimed) { + g_array_unref(vof->claimed); + } + if (vof->of_instances) { + g_hash_table_unref(vof->of_instances); + } + vof->claimed = NULL; + vof->of_instances = NULL; +} + +void vof_build_dt(void *fdt, Vof *vof) +{ + uint32_t phandle = fdt_get_max_phandle(fdt); + int offset, proplen = 0; + const void *prop; + + /* Assign phandles to nodes without predefined phandles (like XICS/XIVE) */ + for (offset = fdt_next_node(fdt, -1, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + prop = fdt_getprop(fdt, offset, "phandle", &proplen); + if (prop) { + continue; + } + ++phandle; + _FDT(fdt_setprop_cell(fdt, offset, "phandle", phandle)); + } + + vof_dt_memory_available(fdt, vof->claimed, vof->claimed_base); +} + +static const TypeInfo vof_machine_if_info = { + .name = TYPE_VOF_MACHINE_IF, + .parent = TYPE_INTERFACE, + .class_size = sizeof(VofMachineIfClass), +}; + +static void vof_machine_if_register_types(void) +{ + type_register_static(&vof_machine_if_info); +} +type_init(vof_machine_if_register_types) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 5697327e4c..1e63f33e9a 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -12,6 +12,7 @@ #include "hw/ppc/spapr_xive.h" /* For SpaprXive */ #include "hw/ppc/xics.h" /* For ICSState */ #include "hw/ppc/spapr_tpm_proxy.h" +#include "hw/ppc/vof.h" struct SpaprVioBus; struct SpaprPhbState; @@ -180,6 +181,7 @@ struct SpaprMachineState { uint64_t kernel_addr; uint32_t initrd_base; long initrd_size; + Vof *vof; uint64_t rtc_offset; /* Now used only during incoming migration */ struct PPCTimebase tb; bool has_graphics; @@ -558,7 +560,9 @@ struct SpaprMachineState { /* Client Architecture support */ #define KVMPPC_H_CAS (KVMPPC_HCALL_BASE + 0x2) #define KVMPPC_H_UPDATE_DT (KVMPPC_HCALL_BASE + 0x3) -#define KVMPPC_HCALL_MAX KVMPPC_H_UPDATE_DT +/* 0x4 was used for KVMPPC_H_UPDATE_PHANDLE in SLOF */ +#define KVMPPC_H_VOF_CLIENT (KVMPPC_HCALL_BASE + 0x5) +#define KVMPPC_HCALL_MAX KVMPPC_H_VOF_CLIENT /* * The hcall range 0xEF00 to 0xEF80 is reserved for use in facilitating @@ -956,4 +960,17 @@ bool spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize, void spapr_set_all_lpcrs(target_ulong value, target_ulong mask); hwaddr spapr_get_rtas_addr(void); bool spapr_memory_hot_unplug_supported(SpaprMachineState *spapr); + +void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, + target_ulong *stack_ptr, Error **errp); +void spapr_vof_quiesce(MachineState *ms); +bool spapr_vof_setprop(MachineState *ms, const char *path, const char *propname, + void *val, int vallen); +target_ulong spapr_h_vof_client(PowerPCCPU *cpu, SpaprMachineState *spapr, + target_ulong opcode, target_ulong *args); +target_ulong spapr_vof_client_architecture_support(MachineState *ms, + CPUState *cs, + target_ulong ovec_addr); +void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt); + #endif /* HW_SPAPR_H */ diff --git a/include/hw/ppc/vof.h b/include/hw/ppc/vof.h new file mode 100644 index 0000000000..640be46163 --- /dev/null +++ b/include/hw/ppc/vof.h @@ -0,0 +1,58 @@ +/* + * Virtual Open Firmware + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef HW_VOF_H +#define HW_VOF_H + +typedef struct Vof { + uint64_t top_addr; /* copied from rma_size */ + GArray *claimed; /* array of SpaprOfClaimed */ + uint64_t claimed_base; + GHashTable *of_instances; /* ihandle -> SpaprOfInstance */ + uint32_t of_instance_last; + char *bootargs; + long fw_size; +} Vof; + +int vof_client_call(MachineState *ms, Vof *vof, void *fdt, + target_ulong args_real); +uint64_t vof_claim(Vof *vof, uint64_t virt, uint64_t size, uint64_t align); +void vof_init(Vof *vof, uint64_t top_addr, Error **errp); +void vof_cleanup(Vof *vof); +void vof_build_dt(void *fdt, Vof *vof); +uint32_t vof_client_open_store(void *fdt, Vof *vof, const char *nodename, + const char *prop, const char *path); + +#define TYPE_VOF_MACHINE_IF "vof-machine-if" + +typedef struct VofMachineIfClass VofMachineIfClass; +DECLARE_CLASS_CHECKERS(VofMachineIfClass, VOF_MACHINE, TYPE_VOF_MACHINE_IF) + +struct VofMachineIfClass { + InterfaceClass parent; + target_ulong (*client_architecture_support)(MachineState *ms, CPUState *cs, + target_ulong vec); + void (*quiesce)(MachineState *ms); + bool (*setprop)(MachineState *ms, const char *path, const char *propname, + void *val, int vallen); +}; + +/* + * Initial stack size is from + * https://www.devicetree.org/open-firmware/bindings/ppc/release/ppc-2_1.html#REF27292 + * + * "Client programs shall be invoked with a valid stack pointer (r1) with + * at least 32K bytes of memory available for stack growth". + */ +#define VOF_STACK_SIZE 0x8000 + +#define VOF_MEM_READ(pa, buf, size) \ + address_space_read(&address_space_memory, \ + (pa), MEMTXATTRS_UNSPECIFIED, (buf), (size)) +#define VOF_MEM_WRITE(pa, buf, size) \ + address_space_write(&address_space_memory, \ + (pa), MEMTXATTRS_UNSPECIFIED, (buf), (size)) + +#endif /* HW_VOF_H */ diff --git a/pc-bios/README b/pc-bios/README index c101c9a04f..d344e3bc1b 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -16,6 +16,10 @@ https://github.com/aik/SLOF, and the image currently in qemu is built from git tag qemu-slof-20210217. +- VOF (Virtual Open Firmware) is a minimalistic firmware to work with + -machine pseries,x-vof=on. When enabled, the firmware acts as a slim shim and + QEMU implements parts of the IEEE 1275 Open Firmware interface. + - sgabios (the Serial Graphics Adapter option ROM) provides a means for legacy x86 software to communicate with an attached serial console as if a video card were attached. The master sources reside in a subversion diff --git a/pc-bios/vof-nvram.bin b/pc-bios/vof-nvram.bin new file mode 100644 index 0000000000000000000000000000000000000000..d183901cf980a91d81c4348bb20487c7bb62a2ec GIT binary patch literal 16384 zcmeI%Jx;?g6bEpZJ8*)oSZeqZi&Z2pKnD)sI4{AHlNb4;RW}a70XPHaW57uo=-#R7 zKSLBhJJ0sdixY3IuY@hzo0r$OmE%T;XE9uh@s1k=AOHafKmY;|fB*y_009U<00Izz z00bZa0SG_<0uX=z1Rwwb2tWV=XCbip6d#B4{{rX#XR%}$Bm^J;0SG|gWP$!?Aq=-I zcT+0Ix{{?1q>9J8r+eW^JK1tYYZZMWQCUwW%0S*~w^p@wfkX-kxMAEA<~5@*g)@mb%KD5!;O~8c)>8rRQBx55=trhk#+1+T3J_ zaf*G4vZAduqy$qda{``6Gnc2DQg7B^s4f5i literal 0 HcmV?d00001 diff --git a/pc-bios/vof.bin b/pc-bios/vof.bin new file mode 100755 index 0000000000000000000000000000000000000000..1ec670be82134adcb5ae128732aff6e371281360 GIT binary patch literal 3784 zcmeHIL1-Lh6n>lC=%gLW9QLr#l}v1e-6f$B_K?xg-PA2?k`e+EC^WLWX18WB$*##L zqwKgdDcGd6vY{31LDNGBdJsJHpr=+43D`ppJ*-fhdMkMGXwf=;Z|0vS*)$~>4}u-| znVJ88^S<}K_ue-||Lg{vfz^9((;= zR2{WQtrd?N131V}{??u$da-4X{5^achQIqYsco$hpzbT*Q3SrDwbWtbHvOlgK%SoO^cXd?|*UBR(E-jM#A^vwOq<4rW;PMn9Gb2(NRw{|F-PFs(0bb%9Qj!*~J zMtsklfRFZNVH1L%$aq|N#Y_x`wK#mF!RZi@e~!HX+t|YtwmXGw%(G=X=D<8QVxX>l z2dnGFJDe|YCH6Ps{Pq5JZVMJ4pv;#&V8o>5r(pnIfy1qs3;O8qF2@w0V=RH#g~vrbA!<)JfkU)-x{0DVo4t z!FwKe?!(}<6s4IP+y_y^CiXM9^LbYE4eCh6CD_F}==njLy1{dn-?a`3j7!g*xYkK& zzc#RC{~2wFLWnP8do_~yTBLIv5FrpsDqtCcEMIHy#vkP|_$JbBvVi^4KtSOcQ zE#1No0bdpPFYFWlmY9VMW}zRmFtB?TE?B^i0lx>c&-;?I4*A3P=Gx!>2`Qf)*dr_D4Q|i9q>n*T-edRfc z!tYierf}xOwsF`R?I&<6hD_@Vt{_MdYHumUUSbnz)YdSyOlLx7+tq>$j(G_WMujh?uservice)) { + return -1; + } + + if (strcmp("instantiate-rtas", (void *)(unsigned long)pargs->args[0])) { + return -1; + } + + rtas = ci_finddevice("/rtas"); + /* rtas-size is set by QEMU depending of FWNMI support */ + ci_getprop(rtas, "rtas-size", &rtassize, sizeof(rtassize)); + if (rtassize < hv_rtas_size) { + return -1; + } + + rtasbase = (void *)(unsigned long) pargs->args[2]; + + memcpy(rtasbase, hv_rtas, hv_rtas_size); + pargs->args[pargs->nargs] = 0; + pargs->args[pargs->nargs + 1] = pargs->args[2]; + + return 0; +} + +void prom_entry(uint32_t args) +{ + if (prom_handle((void *)(unsigned long) args)) { + ci_entry(args); + } +} + +static int call_ci(const char *service, int nargs, int nret, ...) +{ + int i; + struct prom_args args; + va_list list; + + args.service = ADDR(service); + args.nargs = nargs; + args.nret = nret; + + va_start(list, nret); + for (i = 0; i < nargs; i++) { + args.args[i] = va_arg(list, prom_arg_t); + } + va_end(list); + + for (i = 0; i < nret; i++) { + args.args[nargs + i] = 0; + } + + if (ci_entry((uint32_t)(&args)) < 0) { + return PROM_ERROR; + } + + return (nret > 0) ? args.args[nargs] : 0; +} + +void ci_panic(const char *str) +{ + call_ci("exit", 0, 0); +} + +phandle ci_finddevice(const char *path) +{ + return call_ci("finddevice", 1, 1, path); +} + +uint32_t ci_getprop(phandle ph, const char *propname, void *prop, int len) +{ + return call_ci("getprop", 4, 1, ph, propname, prop, len); +} diff --git a/pc-bios/vof/entry.S b/pc-bios/vof/entry.S new file mode 100644 index 0000000000..10a101fb6d --- /dev/null +++ b/pc-bios/vof/entry.S @@ -0,0 +1,49 @@ +#define LOAD32(rn, name) \ + lis rn,name##@h; \ + ori rn,rn,name##@l + +#define ENTRY(func_name) \ + .text; \ + .align 2; \ + .globl .func_name; \ + .func_name: \ + .globl func_name; \ + func_name: + +#define KVMPPC_HCALL_BASE 0xf000 +#define KVMPPC_H_RTAS (KVMPPC_HCALL_BASE + 0x0) +#define KVMPPC_H_VOF_CLIENT (KVMPPC_HCALL_BASE + 0x5) + + . = 0x100 /* Do exactly as SLOF does */ + +ENTRY(_start) + LOAD32(2, __toc_start) + b entry_c + +ENTRY(_prom_entry) + LOAD32(2, __toc_start) + stwu %r1,-112(%r1) + stw %r31,104(%r1) + mflr %r31 + bl prom_entry + nop + mtlr %r31 + lwz %r31,104(%r1) + addi %r1,%r1,112 + blr + +ENTRY(ci_entry) + mr 4,3 + LOAD32(3,KVMPPC_H_VOF_CLIENT) + sc 1 + blr + +/* This is the actual RTAS blob copied to the OS at instantiate-rtas */ +ENTRY(hv_rtas) + mr %r4,%r3 + LOAD32(3,KVMPPC_H_RTAS) + sc 1 + blr + .globl hv_rtas_size +hv_rtas_size: + .long . - hv_rtas; diff --git a/pc-bios/vof/libc.c b/pc-bios/vof/libc.c new file mode 100644 index 0000000000..00c10e6e7d --- /dev/null +++ b/pc-bios/vof/libc.c @@ -0,0 +1,92 @@ +#include "vof.h" + +int strlen(const char *s) +{ + int len = 0; + + while (*s != 0) { + len += 1; + s += 1; + } + + return len; +} + +int strcmp(const char *s1, const char *s2) +{ + while (*s1 != 0 && *s2 != 0) { + if (*s1 != *s2) { + break; + } + s1 += 1; + s2 += 1; + } + + return *s1 - *s2; +} + +void *memcpy(void *dest, const void *src, size_t n) +{ + char *cdest; + const char *csrc = src; + + cdest = dest; + while (n-- > 0) { + *cdest++ = *csrc++; + } + + return dest; +} + +int memcmp(const void *ptr1, const void *ptr2, size_t n) +{ + const unsigned char *p1 = ptr1; + const unsigned char *p2 = ptr2; + + while (n-- > 0) { + if (*p1 != *p2) { + return *p1 - *p2; + } + p1 += 1; + p2 += 1; + } + + return 0; +} + +void *memmove(void *dest, const void *src, size_t n) +{ + char *cdest; + const char *csrc; + int i; + + /* Do the buffers overlap in a bad way? */ + if (src < dest && src + n >= dest) { + /* Copy from end to start */ + cdest = dest + n - 1; + csrc = src + n - 1; + for (i = 0; i < n; i++) { + *cdest-- = *csrc--; + } + } else { + /* Normal copy is possible */ + cdest = dest; + csrc = src; + for (i = 0; i < n; i++) { + *cdest++ = *csrc++; + } + } + + return dest; +} + +void *memset(void *dest, int c, size_t size) +{ + unsigned char *d = (unsigned char *)dest; + + while (size-- > 0) { + *d++ = (unsigned char)c; + } + + return dest; +} diff --git a/pc-bios/vof/main.c b/pc-bios/vof/main.c new file mode 100644 index 0000000000..9fc30d2d09 --- /dev/null +++ b/pc-bios/vof/main.c @@ -0,0 +1,21 @@ +#include "vof.h" + +void do_boot(unsigned long addr, unsigned long _r3, unsigned long _r4) +{ + register unsigned long r3 __asm__("r3") = _r3; + register unsigned long r4 __asm__("r4") = _r4; + register unsigned long r5 __asm__("r5") = (unsigned long) _prom_entry; + + ((client *)(uint32_t)addr)(); +} + +void entry_c(void) +{ + register unsigned long r3 __asm__("r3"); + register unsigned long r4 __asm__("r4"); + register unsigned long r5 __asm__("r5"); + uint64_t initrd = r3, initrdsize = r4; + + boot_from_memory(initrd, initrdsize); + ci_panic("*** No boot target ***\n"); +} diff --git a/pc-bios/vof/vof.h b/pc-bios/vof/vof.h new file mode 100644 index 0000000000..2d89580769 --- /dev/null +++ b/pc-bios/vof/vof.h @@ -0,0 +1,43 @@ +/* + * Virtual Open Firmware + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; +typedef unsigned long long uint64_t; +#define NULL (0) +#define PROM_ERROR (-1u) +typedef unsigned long ihandle; +typedef unsigned long phandle; +typedef int size_t; +typedef void client(void); + +/* globals */ +extern void _prom_entry(void); /* OF CI entry point (i.e. this firmware) */ + +void do_boot(unsigned long addr, unsigned long r3, unsigned long r4); + +/* libc */ +int strlen(const char *s); +int strcmp(const char *s1, const char *s2); +void *memcpy(void *dest, const void *src, size_t n); +int memcmp(const void *ptr1, const void *ptr2, size_t n); +void *memmove(void *dest, const void *src, size_t n); +void *memset(void *dest, int c, size_t size); + +/* CI wrappers */ +void ci_panic(const char *str); +phandle ci_finddevice(const char *path); +uint32_t ci_getprop(phandle ph, const char *propname, void *prop, int len); + +/* booting from -kernel */ +void boot_from_memory(uint64_t initrd, uint64_t initrdsize); + +/* Entry points for CI and RTAS */ +extern uint32_t ci_entry(uint32_t params); +extern unsigned long hv_rtas(unsigned long params); +extern unsigned int hv_rtas_size; diff --git a/pc-bios/vof/vof.lds b/pc-bios/vof/vof.lds new file mode 100644 index 0000000000..1506ab4b01 --- /dev/null +++ b/pc-bios/vof/vof.lds @@ -0,0 +1,48 @@ +OUTPUT_FORMAT("elf32-powerpc") +OUTPUT_ARCH(powerpc:common) + +/* set the entry point */ +ENTRY ( __start ) + +SECTIONS { + __executable_start = .; + + .text : { + *(.text) + } + + __etext = .; + + . = ALIGN(8); + + .data : { + *(.data) + *(.rodata .rodata.*) + *(.got1) + *(.sdata) + *(.opd) + } + + /* FIXME bss at end ??? */ + + . = ALIGN(8); + __bss_start = .; + .bss : { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + } + + . = ALIGN(8); + __bss_end = .; + __bss_size = (__bss_end - __bss_start); + + . = ALIGN(256); + __toc_start = DEFINED (.TOC.) ? .TOC. : ADDR (.got) + 0x8000; + .got : + { + *(.toc .got) + } + . = ALIGN(8); + __toc_end = .; +} diff --git a/tests/qtest/rtas-test.c b/tests/qtest/rtas-test.c index 16751dbd2f..5f1194a6eb 100644 --- a/tests/qtest/rtas-test.c +++ b/tests/qtest/rtas-test.c @@ -5,7 +5,7 @@ #include "libqos/libqos-spapr.h" #include "libqos/rtas.h" -static void test_rtas_get_time_of_day(void) +static void run_test_rtas_get_time_of_day(const char *machine) { QOSState *qs; struct tm tm; @@ -13,7 +13,7 @@ static void test_rtas_get_time_of_day(void) uint64_t ret; time_t t1, t2; - qs = qtest_spapr_boot("-machine pseries"); + qs = qtest_spapr_boot(machine); t1 = time(NULL); ret = qrtas_get_time_of_day(qs->qts, &qs->alloc, &tm, &ns); @@ -24,6 +24,16 @@ static void test_rtas_get_time_of_day(void) qtest_shutdown(qs); } +static void test_rtas_get_time_of_day(void) +{ + run_test_rtas_get_time_of_day("-machine pseries"); +} + +static void test_rtas_get_time_of_day_vof(void) +{ + run_test_rtas_get_time_of_day("-machine pseries,x-vof=on"); +} + int main(int argc, char *argv[]) { const char *arch = qtest_get_arch(); @@ -35,6 +45,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } qtest_add_func("rtas/get-time-of-day", test_rtas_get_time_of_day); + qtest_add_func("rtas/get-time-of-day-vof", test_rtas_get_time_of_day_vof); return g_test_run(); } From patchwork Fri Jul 9 05:17:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366747 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.8 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 A63C4C07E99 for ; Fri, 9 Jul 2021 05:35:40 +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 3B57961442 for ; Fri, 9 Jul 2021 05:35:40 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3B57961442 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:33466 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jAp-0004Zi-BA for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:35:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35284) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itm-0001IE-Qp; Fri, 09 Jul 2021 01:18:02 -0400 Received: from ozlabs.org ([203.11.71.1]:60181) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itl-000233-4V; Fri, 09 Jul 2021 01:18:02 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf35b0z9t5K; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=fmtyaAfW8gexYPiNoF7QBDrbqMXBLaAkCCswKdWHVfQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WScZhKUPKG+fknTaSIHINkKtmFuDQZUa7P4O62Yu4PMZ1MHDA99KcgD1iojlPtTdN SAoiAIcKU35jFpKlop273oC1A+hSmwFlA0qxjeIh1M4zXT6UGigjgZpoLdE47APUi/ plsKVxplN95UDYL3+uSxrXzD3gmacOKwYj0rKoOk= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 23/33] target/ppc: mtmsrd is an illegal instruction on BookE Date: Fri, 9 Jul 2021 15:17:18 +1000 Message-Id: <20210709051728.170203-24-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, qemu-devel@nongnu.org, Nicholas Piggin , qemu-ppc@nongnu.org, Christian Zigotzky , David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Nicholas Piggin MSR is a 32-bit register in BookE and there is no mtmsrd instruction. Cc: Christian Zigotzky Signed-off-by: Nicholas Piggin Message-Id: <20210706051321.609046-1-npiggin@gmail.com> Signed-off-by: David Gibson --- target/ppc/translate.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target/ppc/translate.c b/target/ppc/translate.c index f65d1e81ea..d1f482b0f3 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -4940,6 +4940,11 @@ static void gen_mtcrf(DisasContext *ctx) #if defined(TARGET_PPC64) static void gen_mtmsrd(DisasContext *ctx) { + if (unlikely(!is_book3s_arch2x(ctx))) { + gen_invalid(ctx); + return; + } + CHK_SV; #if !defined(CONFIG_USER_ONLY) From patchwork Fri Jul 9 05:17:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366751 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.8 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 1F577C07E99 for ; Fri, 9 Jul 2021 05:37:39 +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 9385F61433 for ; Fri, 9 Jul 2021 05:37:38 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9385F61433 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:39040 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jCi-0008Iv-Od for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:37:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35442) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuF-0002O4-9z; Fri, 09 Jul 2021 01:18:31 -0400 Received: from bilbo.ozlabs.org ([2401:3900:2:1::2]:36381 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iu6-00023s-Nj; Fri, 09 Jul 2021 01:18:30 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf3R3mz9t5m; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=5Mwafl9cb5rvOw8u3y1GQcxACNk6VZ56c1NcMa7TQ+4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MejsRwpabgxswHU6xa2d9EWes889lK0liRjpxGASOP2ca5xLVRmRG6AlJQDYv3yx+ V2CWeGjtvVQm6EZlBLuIw9Q2RR+N/ygu+gtwMubMqTVcfhujDwp5hpg+ideeDiIngW rrvuSeCuzP99VlR2x1ko+c3w/PC8CYK5S5KU3omA= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 24/33] ppc/pegasos2: Introduce Pegasos2MachineState structure Date: Fri, 9 Jul 2021 15:17:19 +1000 Message-Id: <20210709051728.170203-25-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , qemu-devel@nongnu.org, qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: BALATON Zoltan Add own machine state structure which will be used to store state needed for firmware emulation. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: <7f6d5fbf4f70c64dba001483174a2921dd616ecd.1624811233.git.balaton@eik.bme.hu> Signed-off-by: David Gibson --- hw/ppc/pegasos2.c | 50 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index 0bfd0928aa..07971175c9 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -1,7 +1,7 @@ /* * QEMU PowerPC CHRP (Genesi/bPlan Pegasos II) hardware System Emulator * - * Copyright (c) 2018-2020 BALATON Zoltan + * Copyright (c) 2018-2021 BALATON Zoltan * * This work is licensed under the GNU GPL license version 2 or later. * @@ -41,6 +41,15 @@ #define BUS_FREQ_HZ 133333333 +#define TYPE_PEGASOS2_MACHINE MACHINE_TYPE_NAME("pegasos2") +OBJECT_DECLARE_TYPE(Pegasos2MachineState, MachineClass, PEGASOS2_MACHINE) + +struct Pegasos2MachineState { + MachineState parent_obj; + PowerPCCPU *cpu; + DeviceState *mv; +}; + static void pegasos2_cpu_reset(void *opaque) { PowerPCCPU *cpu = opaque; @@ -51,9 +60,9 @@ static void pegasos2_cpu_reset(void *opaque) static void pegasos2_init(MachineState *machine) { - PowerPCCPU *cpu = NULL; + Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine); + CPUPPCState *env; MemoryRegion *rom = g_new(MemoryRegion, 1); - DeviceState *mv; PCIBus *pci_bus; PCIDevice *dev; I2CBus *i2c_bus; @@ -63,15 +72,16 @@ static void pegasos2_init(MachineState *machine) uint8_t *spd_data; /* init CPU */ - cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); - if (PPC_INPUT(&cpu->env) != PPC_FLAGS_INPUT_6xx) { + pm->cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); + env = &pm->cpu->env; + if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) { error_report("Incompatible CPU, only 6xx bus supported"); exit(1); } /* Set time-base frequency */ - cpu_ppc_tb_init(&cpu->env, BUS_FREQ_HZ / 4); - qemu_register_reset(pegasos2_cpu_reset, cpu); + cpu_ppc_tb_init(env, BUS_FREQ_HZ / 4); + qemu_register_reset(pegasos2_cpu_reset, pm->cpu); /* RAM */ memory_region_add_subregion(get_system_memory(), 0, machine->ram); @@ -96,16 +106,16 @@ static void pegasos2_init(MachineState *machine) g_free(filename); /* Marvell Discovery II system controller */ - mv = DEVICE(sysbus_create_simple(TYPE_MV64361, -1, - ((qemu_irq *)cpu->env.irq_inputs)[PPC6xx_INPUT_INT])); - pci_bus = mv64361_get_pci_bus(mv, 1); + pm->mv = DEVICE(sysbus_create_simple(TYPE_MV64361, -1, + ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT])); + pci_bus = mv64361_get_pci_bus(pm->mv, 1); /* VIA VT8231 South Bridge (multifunction PCI device) */ /* VT8231 function 0: PCI-to-ISA Bridge */ dev = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(12, 0), true, TYPE_VT8231_ISA); qdev_connect_gpio_out(DEVICE(dev), 0, - qdev_get_gpio_in_named(mv, "gpp", 31)); + qdev_get_gpio_in_named(pm->mv, "gpp", 31)); /* VT8231 function 1: IDE Controller */ dev = pci_create_simple(pci_bus, PCI_DEVFN(12, 1), "via-ide"); @@ -129,8 +139,10 @@ static void pegasos2_init(MachineState *machine) pci_vga_init(pci_bus); } -static void pegasos2_machine(MachineClass *mc) +static void pegasos2_machine_class_init(ObjectClass *oc, void *data) { + MachineClass *mc = MACHINE_CLASS(oc); + mc->desc = "Genesi/bPlan Pegasos II"; mc->init = pegasos2_init; mc->block_default_type = IF_IDE; @@ -141,4 +153,16 @@ static void pegasos2_machine(MachineClass *mc) mc->default_ram_size = 512 * MiB; } -DEFINE_MACHINE("pegasos2", pegasos2_machine) +static const TypeInfo pegasos2_machine_info = { + .name = TYPE_PEGASOS2_MACHINE, + .parent = TYPE_MACHINE, + .class_init = pegasos2_machine_class_init, + .instance_size = sizeof(Pegasos2MachineState), +}; + +static void pegasos2_machine_register_types(void) +{ + type_register_static(&pegasos2_machine_info); +} + +type_init(pegasos2_machine_register_types) From patchwork Fri Jul 9 05:17:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366741 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.8 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 7EC87C07E99 for ; Fri, 9 Jul 2021 05:33:12 +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 2C84661442 for ; Fri, 9 Jul 2021 05:33:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2C84661442 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:55054 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1j8R-0000Bb-Cz for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:33:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35298) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1itq-0001Oi-5k; Fri, 09 Jul 2021 01:18:06 -0400 Received: from ozlabs.org ([203.11.71.1]:54201) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1ito-00024t-Gc; Fri, 09 Jul 2021 01:18:05 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf4lFZz9t6h; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=Qybi7wOY2Hanuu5XVj+JM8Y/CJrO3KMSTJy/4e3jiKw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=K7Vrs5vHdld3Yb+hYnvUv8RGNfRoA0/krxovyDqyciCrsch9Pz+sn6QvHs7NzBFSK kzule3rrNOu7vSMvCI6JfjlNaRzhDr0jfqRlBl+SJp/yqQqYsSrW8d/idqhjQlFE1C NxJG7nWCJLDD4Vf9s8Q6KbX0fhiQHa9168Kf1BzE= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 25/33] target/ppc: Allow virtual hypervisor on CPU without HV Date: Fri, 9 Jul 2021 15:17:20 +1000 Message-Id: <20210709051728.170203-26-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: BALATON Zoltan Change the assert in ppc_store_sdr1() to allow vhyp to be set on CPUs without HV bit. This allows using the vhyp interface for firmware emulation on pegasos2. Signed-off-by: BALATON Zoltan Message-Id: <21c7745aabbb68fcc50bb2ffaf16b939ba21261c.1624811233.git.balaton@eik.bme.hu> Signed-off-by: David Gibson --- target/ppc/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c index 19d67b5b07..a29299882a 100644 --- a/target/ppc/cpu.c +++ b/target/ppc/cpu.c @@ -72,7 +72,7 @@ void ppc_store_sdr1(CPUPPCState *env, target_ulong value) { PowerPCCPU *cpu = env_archcpu(env); qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value); - assert(!cpu->vhyp); + assert(!cpu->env.has_hv_mode || !cpu->vhyp); #if defined(TARGET_PPC64) if (mmu_is_64bit(env->mmu_model)) { target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE; From patchwork Fri Jul 9 05:17:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366769 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.8 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 6BA26C07E99 for ; Fri, 9 Jul 2021 05:49:08 +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 F39E16143E for ; Fri, 9 Jul 2021 05:49:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F39E16143E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:33624 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jNr-00075E-0f for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:49:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35432) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuD-0002MI-IN; Fri, 09 Jul 2021 01:18:30 -0400 Received: from bilbo.ozlabs.org ([2401:3900:2:1::2]:46017 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iu7-00024i-R0; Fri, 09 Jul 2021 01:18:29 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf4L33z9t6S; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=3U0sBL2BFTOAco2yKBEHlINhjEAC4B8ZVgzjvIoshYs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PkTLkfb4MrNPed/XEmu914VPMTp9IlaMu3Z0sWfKcfh88E6Ea08mjluM2Yok1EXFf /u/YSOjOkcaEk20SfSboWbxXmElcO6+BSnb8q6Baq9512xh8MxlB3WoE5jK9PxDnFo NJMrejS5YCOhSrOBRNdqG8R/JAjpH50qh9QBIQd0= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 26/33] target/ppc/spapr: Update H_GET_CPU_CHARACTERISTICS L1D cache flush bits Date: Fri, 9 Jul 2021 15:17:21 +1000 Message-Id: <20210709051728.170203-27-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, qemu-ppc@nongnu.org, qemu-devel@nongnu.org, Nicholas Piggin , David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Nicholas Piggin There are several new L1D cache flush bits added to the hcall which reflect hardware security features for speculative cache access issues. These behaviours are now being specified as negative in order to simplify patched kernel compatibility with older firmware (a new problem found in existing systems would automatically be vulnerable). [dwg: Technically this changes behaviour for existing machine types. After discussion with Nick, we've determined this is safe, because the worst that will happen if a guest gets the wrong information due to a migration is that it will perform some unnecessary workarounds, but will remain correct and secure (well, as secure as it was going to be anyway). In addition the change only affects cap-cfpc=safe which is not enabled by default, and in fact is not possible to set on any current hardware (though it's expected it will be possible on POWER10)] Signed-off-by: Nicholas Piggin Message-Id: <20210615044107.1481608-1-npiggin@gmail.com> Signed-off-by: David Gibson --- hw/ppc/spapr_hcall.c | 2 ++ include/hw/ppc/spapr.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 03fc191599..80ae8eaadd 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1318,6 +1318,8 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, behaviour |= H_CPU_BEHAV_L1D_FLUSH_PR; break; case SPAPR_CAP_FIXED: + behaviour |= H_CPU_BEHAV_NO_L1D_FLUSH_ENTRY; + behaviour |= H_CPU_BEHAV_NO_L1D_FLUSH_UACCESS; break; default: /* broken */ assert(safe_cache == SPAPR_CAP_BROKEN); diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 1e63f33e9a..a25e69fe4c 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -400,10 +400,13 @@ struct SpaprMachineState { #define H_CPU_CHAR_THR_RECONF_TRIG PPC_BIT(6) #define H_CPU_CHAR_CACHE_COUNT_DIS PPC_BIT(7) #define H_CPU_CHAR_BCCTR_FLUSH_ASSIST PPC_BIT(9) + #define H_CPU_BEHAV_FAVOUR_SECURITY PPC_BIT(0) #define H_CPU_BEHAV_L1D_FLUSH_PR PPC_BIT(1) #define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR PPC_BIT(2) #define H_CPU_BEHAV_FLUSH_COUNT_CACHE PPC_BIT(5) +#define H_CPU_BEHAV_NO_L1D_FLUSH_ENTRY PPC_BIT(7) +#define H_CPU_BEHAV_NO_L1D_FLUSH_UACCESS PPC_BIT(8) /* Each control block has to be on a 4K boundary */ #define H_CB_ALIGNMENT 4096 From patchwork Fri Jul 9 05:17:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366765 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.8 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 DA6D4C07E99 for ; Fri, 9 Jul 2021 05:47:34 +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 52D1461447 for ; Fri, 9 Jul 2021 05:47:34 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 52D1461447 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:57868 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jML-0004R7-F7 for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:47:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35502) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuK-0002ZL-J6; Fri, 09 Jul 2021 01:18:36 -0400 Received: from ozlabs.org ([2401:3900:2:1::2]:44721) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iu9-000255-E4; Fri, 09 Jul 2021 01:18:36 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf5CySz9t6g; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=JyeYHGST+GRqn9qKMti4dv0q6FEGJdZcS+NJ2rC2SHQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VsGHufbqVZi3a9P1JYFKKBBznW6eC5isgaF6Sz+YMaNcfvgFTPU/2O3dUQLu0gNhv Y60S9RbcTcD2JcogQhXru3HvN0NtqaiKlAbPhZ1u2eLCTgmNUPffYbi7UMoRWWGBML WKS6P/ZrdGEald/hcW6iRxGQ1+aXcKwIFgL9Q3Nc= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 27/33] ppc/pegasos2: Use Virtual Open Firmware as firmware replacement Date: Fri, 9 Jul 2021 15:17:22 +1000 Message-Id: <20210709051728.170203-28-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: BALATON Zoltan The pegasos2 board comes with an Open Firmware compliant ROM based on SmartFirmware but it has some changes that are not open source therefore the ROM binary cannot be included in QEMU. Guests running on the board however depend on services provided by the firmware. The Virtual Open Firmware recently added to QEMU implements a minimal set of these services to allow some guests to boot without the original firmware. This patch adds VOF as the default firmware for pegasos2 which allows booting Linux and MorphOS via -kernel option while a ROM image can still be used with -bios for guests that don't run with VOF. Signed-off-by: BALATON Zoltan Message-Id: <1d6ed6f290c5c1f0b5a1e1c51cf1151452d70d9a.1624811233.git.balaton@eik.bme.hu> Signed-off-by: David Gibson --- hw/ppc/Kconfig | 1 + hw/ppc/pegasos2.c | 602 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 601 insertions(+), 2 deletions(-) diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig index 67630f80e1..7fcafec60a 100644 --- a/hw/ppc/Kconfig +++ b/hw/ppc/Kconfig @@ -76,6 +76,7 @@ config PEGASOS2 select VT82C686 select IDE_VIA select SMBUS_EEPROM + select VOF # This should come with VT82C686 select ACPI_X86 diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index 07971175c9..f1741a4512 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -34,13 +34,33 @@ #include "trace.h" #include "qemu/datadir.h" #include "sysemu/device_tree.h" +#include "hw/ppc/vof.h" -#define PROM_FILENAME "pegasos2.rom" +#include + +#define PROM_FILENAME "vof.bin" #define PROM_ADDR 0xfff00000 #define PROM_SIZE 0x80000 +#define KVMPPC_HCALL_BASE 0xf000 +#define KVMPPC_H_VOF_CLIENT (KVMPPC_HCALL_BASE + 0x5) + +#define H_SUCCESS 0 +#define H_PRIVILEGE -3 /* Caller not privileged */ +#define H_PARAMETER -4 /* Parameter invalid, out-of-range or conflicting */ + #define BUS_FREQ_HZ 133333333 +#define PCI0_MEM_BASE 0xc0000000 +#define PCI0_MEM_SIZE 0x20000000 +#define PCI0_IO_BASE 0xf8000000 +#define PCI0_IO_SIZE 0x10000 + +#define PCI1_MEM_BASE 0x80000000 +#define PCI1_MEM_SIZE 0x40000000 +#define PCI1_IO_BASE 0xfe000000 +#define PCI1_IO_SIZE 0x10000 + #define TYPE_PEGASOS2_MACHINE MACHINE_TYPE_NAME("pegasos2") OBJECT_DECLARE_TYPE(Pegasos2MachineState, MachineClass, PEGASOS2_MACHINE) @@ -48,14 +68,26 @@ struct Pegasos2MachineState { MachineState parent_obj; PowerPCCPU *cpu; DeviceState *mv; + Vof *vof; + void *fdt_blob; + uint64_t kernel_addr; + uint64_t kernel_entry; + uint64_t kernel_size; }; +static void *build_fdt(MachineState *machine, int *fdt_size); + static void pegasos2_cpu_reset(void *opaque) { PowerPCCPU *cpu = opaque; + Pegasos2MachineState *pm = PEGASOS2_MACHINE(current_machine); cpu_reset(CPU(cpu)); cpu->env.spr[SPR_HID1] = 7ULL << 28; + if (pm->vof) { + cpu->env.gpr[1] = 2 * VOF_STACK_SIZE - 0x20; + cpu->env.nip = 0x100; + } } static void pegasos2_init(MachineState *machine) @@ -92,18 +124,24 @@ static void pegasos2_init(MachineState *machine) error_report("Could not find firmware '%s'", fwname); exit(1); } + if (!machine->firmware && !pm->vof) { + pm->vof = g_malloc0(sizeof(*pm->vof)); + } memory_region_init_rom(rom, NULL, "pegasos2.rom", PROM_SIZE, &error_fatal); memory_region_add_subregion(get_system_memory(), PROM_ADDR, rom); sz = load_elf(filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); if (sz <= 0) { - sz = load_image_targphys(filename, PROM_ADDR, PROM_SIZE); + sz = load_image_targphys(filename, pm->vof ? 0 : PROM_ADDR, PROM_SIZE); } if (sz <= 0 || sz > PROM_SIZE) { error_report("Could not load firmware '%s'", filename); exit(1); } g_free(filename); + if (pm->vof) { + pm->vof->fw_size = sz; + } /* Marvell Discovery II system controller */ pm->mv = DEVICE(sysbus_create_simple(TYPE_MV64361, -1, @@ -137,20 +175,185 @@ static void pegasos2_init(MachineState *machine) /* other PC hardware */ pci_vga_init(pci_bus); + + if (machine->kernel_filename) { + sz = load_elf(machine->kernel_filename, NULL, NULL, NULL, + &pm->kernel_entry, &pm->kernel_addr, NULL, NULL, 1, + PPC_ELF_MACHINE, 0, 0); + if (sz <= 0) { + error_report("Could not load kernel '%s'", + machine->kernel_filename); + exit(1); + } + pm->kernel_size = sz; + if (!pm->vof) { + warn_report("Option -kernel may be ineffective with -bios."); + } + } + if (machine->kernel_cmdline && !pm->vof) { + warn_report("Option -append may be ineffective with -bios."); + } +} + +static void pegasos2_pci_config_write(AddressSpace *as, int bus, uint32_t addr, + uint32_t len, uint32_t val) +{ + hwaddr pcicfg = (bus ? 0xf1000c78 : 0xf1000cf8); + + stl_le_phys(as, pcicfg, addr | BIT(31)); + switch (len) { + case 4: + stl_le_phys(as, pcicfg + 4, val); + break; + case 2: + stw_le_phys(as, pcicfg + 4, val); + break; + case 1: + stb_phys(as, pcicfg + 4, val); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid length\n", __func__); + break; + } +} + +static void pegasos2_machine_reset(MachineState *machine) +{ + Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine); + AddressSpace *as = CPU(pm->cpu)->as; + void *fdt; + uint64_t d[2]; + int sz; + + qemu_devices_reset(); + if (!pm->vof) { + return; /* Firmware should set up machine so nothing to do */ + } + + /* Otherwise, set up devices that board firmware would normally do */ + stl_le_phys(as, 0xf1000000, 0x28020ff); + stl_le_phys(as, 0xf1000278, 0xa31fc); + stl_le_phys(as, 0xf100f300, 0x11ff0400); + stl_le_phys(as, 0xf100f10c, 0x80000000); + stl_le_phys(as, 0xf100001c, 0x8000000); + pegasos2_pci_config_write(as, 0, PCI_COMMAND, 2, PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pegasos2_pci_config_write(as, 1, PCI_COMMAND, 2, PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 0) << 8) | + PCI_INTERRUPT_LINE, 2, 0x9); + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 0) << 8) | + 0x50, 1, 0x2); + + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) | + PCI_INTERRUPT_LINE, 2, 0x109); + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) | + PCI_CLASS_PROG, 1, 0xf); + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) | + 0x40, 1, 0xb); + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) | + 0x50, 4, 0x17171717); + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 1) << 8) | + PCI_COMMAND, 2, 0x87); + + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 2) << 8) | + PCI_INTERRUPT_LINE, 2, 0x409); + + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 3) << 8) | + PCI_INTERRUPT_LINE, 2, 0x409); + + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) | + PCI_INTERRUPT_LINE, 2, 0x9); + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) | + 0x48, 4, 0xf00); + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) | + 0x40, 4, 0x558020); + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 4) << 8) | + 0x90, 4, 0xd00); + + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 5) << 8) | + PCI_INTERRUPT_LINE, 2, 0x309); + + pegasos2_pci_config_write(as, 1, (PCI_DEVFN(12, 6) << 8) | + PCI_INTERRUPT_LINE, 2, 0x309); + + /* Device tree and VOF set up */ + vof_init(pm->vof, machine->ram_size, &error_fatal); + if (vof_claim(pm->vof, 0, VOF_STACK_SIZE, VOF_STACK_SIZE) == -1) { + error_report("Memory allocation for stack failed"); + exit(1); + } + if (pm->kernel_size && + vof_claim(pm->vof, pm->kernel_addr, pm->kernel_size, 0) == -1) { + error_report("Memory for kernel is in use"); + exit(1); + } + fdt = build_fdt(machine, &sz); + /* FIXME: VOF assumes entry is same as load address */ + d[0] = cpu_to_be64(pm->kernel_entry); + d[1] = cpu_to_be64(pm->kernel_size - (pm->kernel_entry - pm->kernel_addr)); + qemu_fdt_setprop(fdt, "/chosen", "qemu,boot-kernel", d, sizeof(d)); + + qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); + g_free(pm->fdt_blob); + pm->fdt_blob = fdt; + + vof_build_dt(fdt, pm->vof); + vof_client_open_store(fdt, pm->vof, "/chosen", "stdout", "/failsafe"); + pm->cpu->vhyp = PPC_VIRTUAL_HYPERVISOR(machine); +} + +static void pegasos2_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) +{ + Pegasos2MachineState *pm = PEGASOS2_MACHINE(vhyp); + CPUPPCState *env = &cpu->env; + + /* The TCG path should also be holding the BQL at this point */ + g_assert(qemu_mutex_iothread_locked()); + + if (msr_pr) { + qemu_log_mask(LOG_GUEST_ERROR, "Hypercall made with MSR[PR]=1\n"); + env->gpr[3] = H_PRIVILEGE; + } else if (env->gpr[3] == KVMPPC_H_VOF_CLIENT) { + int ret = vof_client_call(MACHINE(pm), pm->vof, pm->fdt_blob, + env->gpr[4]); + env->gpr[3] = (ret ? H_PARAMETER : H_SUCCESS); + } else { + qemu_log_mask(LOG_GUEST_ERROR, "Unsupported hypercall " TARGET_FMT_lx + "\n", env->gpr[3]); + env->gpr[3] = -1; + } +} + +static void vhyp_nop(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) +{ +} + +static target_ulong vhyp_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp) +{ + return POWERPC_CPU(current_cpu)->env.spr[SPR_SDR1]; } static void pegasos2_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc); mc->desc = "Genesi/bPlan Pegasos II"; mc->init = pegasos2_init; + mc->reset = pegasos2_machine_reset; mc->block_default_type = IF_IDE; mc->default_boot_order = "cd"; mc->default_display = "std"; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("7400_v2.9"); mc->default_ram_id = "pegasos2.ram"; mc->default_ram_size = 512 * MiB; + + vhc->hypercall = pegasos2_hypercall; + vhc->cpu_exec_enter = vhyp_nop; + vhc->cpu_exec_exit = vhyp_nop; + vhc->encode_hpt_for_kvm_pr = vhyp_encode_hpt_for_kvm_pr; } static const TypeInfo pegasos2_machine_info = { @@ -158,6 +361,10 @@ static const TypeInfo pegasos2_machine_info = { .parent = TYPE_MACHINE, .class_init = pegasos2_machine_class_init, .instance_size = sizeof(Pegasos2MachineState), + .interfaces = (InterfaceInfo[]) { + { TYPE_PPC_VIRTUAL_HYPERVISOR }, + { } + }, }; static void pegasos2_machine_register_types(void) @@ -166,3 +373,394 @@ static void pegasos2_machine_register_types(void) } type_init(pegasos2_machine_register_types) + +/* FDT creation for passing to firmware */ + +typedef struct { + void *fdt; + const char *path; +} FDTInfo; + +/* We do everything in reverse order so it comes out right in the tree */ + +static void dt_ide(PCIBus *bus, PCIDevice *d, FDTInfo *fi) +{ + qemu_fdt_setprop_string(fi->fdt, fi->path, "device_type", "spi"); +} + +static void dt_usb(PCIBus *bus, PCIDevice *d, FDTInfo *fi) +{ + qemu_fdt_setprop_cell(fi->fdt, fi->path, "#size-cells", 0); + qemu_fdt_setprop_cell(fi->fdt, fi->path, "#address-cells", 1); + qemu_fdt_setprop_string(fi->fdt, fi->path, "device_type", "usb"); +} + +static void dt_isa(PCIBus *bus, PCIDevice *d, FDTInfo *fi) +{ + GString *name = g_string_sized_new(64); + uint32_t cells[3]; + + qemu_fdt_setprop_cell(fi->fdt, fi->path, "#size-cells", 1); + qemu_fdt_setprop_cell(fi->fdt, fi->path, "#address-cells", 2); + qemu_fdt_setprop_string(fi->fdt, fi->path, "device_type", "isa"); + qemu_fdt_setprop_string(fi->fdt, fi->path, "name", "isa"); + + /* addional devices */ + g_string_printf(name, "%s/lpt@i3bc", fi->path); + qemu_fdt_add_subnode(fi->fdt, name->str); + qemu_fdt_setprop_cell(fi->fdt, name->str, "clock-frequency", 0); + cells[0] = cpu_to_be32(7); + cells[1] = 0; + qemu_fdt_setprop(fi->fdt, name->str, "interrupts", + cells, 2 * sizeof(cells[0])); + cells[0] = cpu_to_be32(1); + cells[1] = cpu_to_be32(0x3bc); + cells[2] = cpu_to_be32(8); + qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0])); + qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "lpt"); + qemu_fdt_setprop_string(fi->fdt, name->str, "name", "lpt"); + + g_string_printf(name, "%s/fdc@i3f0", fi->path); + qemu_fdt_add_subnode(fi->fdt, name->str); + qemu_fdt_setprop_cell(fi->fdt, name->str, "clock-frequency", 0); + cells[0] = cpu_to_be32(6); + cells[1] = 0; + qemu_fdt_setprop(fi->fdt, name->str, "interrupts", + cells, 2 * sizeof(cells[0])); + cells[0] = cpu_to_be32(1); + cells[1] = cpu_to_be32(0x3f0); + cells[2] = cpu_to_be32(8); + qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0])); + qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "fdc"); + qemu_fdt_setprop_string(fi->fdt, name->str, "name", "fdc"); + + g_string_printf(name, "%s/timer@i40", fi->path); + qemu_fdt_add_subnode(fi->fdt, name->str); + qemu_fdt_setprop_cell(fi->fdt, name->str, "clock-frequency", 0); + cells[0] = cpu_to_be32(1); + cells[1] = cpu_to_be32(0x40); + cells[2] = cpu_to_be32(8); + qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0])); + qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "timer"); + qemu_fdt_setprop_string(fi->fdt, name->str, "name", "timer"); + + g_string_printf(name, "%s/rtc@i70", fi->path); + qemu_fdt_add_subnode(fi->fdt, name->str); + qemu_fdt_setprop_string(fi->fdt, name->str, "compatible", "ds1385-rtc"); + qemu_fdt_setprop_cell(fi->fdt, name->str, "clock-frequency", 0); + cells[0] = cpu_to_be32(8); + cells[1] = 0; + qemu_fdt_setprop(fi->fdt, name->str, "interrupts", + cells, 2 * sizeof(cells[0])); + cells[0] = cpu_to_be32(1); + cells[1] = cpu_to_be32(0x70); + cells[2] = cpu_to_be32(2); + qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0])); + qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "rtc"); + qemu_fdt_setprop_string(fi->fdt, name->str, "name", "rtc"); + + g_string_printf(name, "%s/keyboard@i60", fi->path); + qemu_fdt_add_subnode(fi->fdt, name->str); + cells[0] = cpu_to_be32(1); + cells[1] = 0; + qemu_fdt_setprop(fi->fdt, name->str, "interrupts", + cells, 2 * sizeof(cells[0])); + cells[0] = cpu_to_be32(1); + cells[1] = cpu_to_be32(0x60); + cells[2] = cpu_to_be32(5); + qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0])); + qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "keyboard"); + qemu_fdt_setprop_string(fi->fdt, name->str, "name", "keyboard"); + + g_string_printf(name, "%s/8042@i60", fi->path); + qemu_fdt_add_subnode(fi->fdt, name->str); + qemu_fdt_setprop_cell(fi->fdt, name->str, "#interrupt-cells", 2); + qemu_fdt_setprop_cell(fi->fdt, name->str, "#size-cells", 0); + qemu_fdt_setprop_cell(fi->fdt, name->str, "#address-cells", 1); + qemu_fdt_setprop_string(fi->fdt, name->str, "interrupt-controller", ""); + qemu_fdt_setprop_cell(fi->fdt, name->str, "clock-frequency", 0); + cells[0] = cpu_to_be32(1); + cells[1] = cpu_to_be32(0x60); + cells[2] = cpu_to_be32(5); + qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0])); + qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", ""); + qemu_fdt_setprop_string(fi->fdt, name->str, "name", "8042"); + + g_string_printf(name, "%s/serial@i2f8", fi->path); + qemu_fdt_add_subnode(fi->fdt, name->str); + qemu_fdt_setprop_cell(fi->fdt, name->str, "clock-frequency", 0); + cells[0] = cpu_to_be32(3); + cells[1] = 0; + qemu_fdt_setprop(fi->fdt, name->str, "interrupts", + cells, 2 * sizeof(cells[0])); + cells[0] = cpu_to_be32(1); + cells[1] = cpu_to_be32(0x2f8); + cells[2] = cpu_to_be32(8); + qemu_fdt_setprop(fi->fdt, name->str, "reg", cells, 3 * sizeof(cells[0])); + qemu_fdt_setprop_string(fi->fdt, name->str, "device_type", "serial"); + qemu_fdt_setprop_string(fi->fdt, name->str, "name", "serial"); + + g_string_free(name, TRUE); +} + +static struct { + const char *id; + const char *name; + void (*dtf)(PCIBus *bus, PCIDevice *d, FDTInfo *fi); +} device_map[] = { + { "pci11ab,6460", "host", NULL }, + { "pci1106,8231", "isa", dt_isa }, + { "pci1106,571", "ide", dt_ide }, + { "pci1106,3044", "firewire", NULL }, + { "pci1106,3038", "usb", dt_usb }, + { "pci1106,8235", "other", NULL }, + { "pci1106,3058", "sound", NULL }, + { NULL, NULL } +}; + +static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque) +{ + FDTInfo *fi = opaque; + GString *node = g_string_new(NULL); + uint32_t cells[(PCI_NUM_REGIONS + 1) * 5]; + int i, j; + const char *name = NULL; + g_autofree const gchar *pn = g_strdup_printf("pci%x,%x", + pci_get_word(&d->config[PCI_VENDOR_ID]), + pci_get_word(&d->config[PCI_DEVICE_ID])); + + for (i = 0; device_map[i].id; i++) { + if (!strcmp(pn, device_map[i].id)) { + name = device_map[i].name; + break; + } + } + g_string_printf(node, "%s/%s@%x", fi->path, (name ?: pn), + PCI_SLOT(d->devfn)); + if (PCI_FUNC(d->devfn)) { + g_string_append_printf(node, ",%x", PCI_FUNC(d->devfn)); + } + + qemu_fdt_add_subnode(fi->fdt, node->str); + if (device_map[i].dtf) { + FDTInfo cfi = { fi->fdt, node->str }; + device_map[i].dtf(bus, d, &cfi); + } + cells[0] = cpu_to_be32(d->devfn << 8); + cells[1] = 0; + cells[2] = 0; + cells[3] = 0; + cells[4] = 0; + j = 5; + for (i = 0; i < PCI_NUM_REGIONS; i++) { + if (!d->io_regions[i].size) { + continue; + } + cells[j] = cpu_to_be32(d->devfn << 8 | (PCI_BASE_ADDRESS_0 + i * 4)); + if (d->io_regions[i].type & PCI_BASE_ADDRESS_SPACE_IO) { + cells[j] |= cpu_to_be32(1 << 24); + } else { + cells[j] |= cpu_to_be32(2 << 24); + if (d->io_regions[i].type & PCI_BASE_ADDRESS_MEM_PREFETCH) { + cells[j] |= cpu_to_be32(4 << 28); + } + } + cells[j + 1] = 0; + cells[j + 2] = 0; + cells[j + 3] = cpu_to_be32(d->io_regions[i].size >> 32); + cells[j + 4] = cpu_to_be32(d->io_regions[i].size); + j += 5; + } + qemu_fdt_setprop(fi->fdt, node->str, "reg", cells, j * sizeof(cells[0])); + qemu_fdt_setprop_string(fi->fdt, node->str, "name", name ?: pn); + if (pci_get_byte(&d->config[PCI_INTERRUPT_PIN])) { + qemu_fdt_setprop_cell(fi->fdt, node->str, "interrupts", + pci_get_byte(&d->config[PCI_INTERRUPT_PIN])); + } + /* Pegasos2 firmware has subsystem-id amd subsystem-vendor-id swapped */ + qemu_fdt_setprop_cell(fi->fdt, node->str, "subsystem-vendor-id", + pci_get_word(&d->config[PCI_SUBSYSTEM_ID])); + qemu_fdt_setprop_cell(fi->fdt, node->str, "subsystem-id", + pci_get_word(&d->config[PCI_SUBSYSTEM_VENDOR_ID])); + cells[0] = pci_get_long(&d->config[PCI_CLASS_REVISION]); + qemu_fdt_setprop_cell(fi->fdt, node->str, "class-code", cells[0] >> 8); + qemu_fdt_setprop_cell(fi->fdt, node->str, "revision-id", cells[0] && 0xff); + qemu_fdt_setprop_cell(fi->fdt, node->str, "device-id", + pci_get_word(&d->config[PCI_DEVICE_ID])); + qemu_fdt_setprop_cell(fi->fdt, node->str, "vendor-id", + pci_get_word(&d->config[PCI_VENDOR_ID])); + + g_string_free(node, TRUE); +} + +static void *build_fdt(MachineState *machine, int *fdt_size) +{ + Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine); + PowerPCCPU *cpu = pm->cpu; + PCIBus *pci_bus; + FDTInfo fi; + uint32_t cells[16]; + void *fdt = create_device_tree(fdt_size); + + fi.fdt = fdt; + + /* root node */ + qemu_fdt_setprop_string(fdt, "/", "CODEGEN,description", + "Pegasos CHRP PowerPC System"); + qemu_fdt_setprop_string(fdt, "/", "CODEGEN,board", "Pegasos2"); + qemu_fdt_setprop_string(fdt, "/", "CODEGEN,vendor", "bplan GmbH"); + qemu_fdt_setprop_string(fdt, "/", "revision", "2B"); + qemu_fdt_setprop_string(fdt, "/", "model", "Pegasos2"); + qemu_fdt_setprop_string(fdt, "/", "device_type", "chrp"); + qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 1); + qemu_fdt_setprop_string(fdt, "/", "name", "bplan,Pegasos2"); + + /* pci@c0000000 */ + qemu_fdt_add_subnode(fdt, "/pci@c0000000"); + cells[0] = 0; + cells[1] = 0; + qemu_fdt_setprop(fdt, "/pci@c0000000", "bus-range", + cells, 2 * sizeof(cells[0])); + qemu_fdt_setprop_cell(fdt, "/pci@c0000000", "pci-bridge-number", 1); + cells[0] = cpu_to_be32(PCI0_MEM_BASE); + cells[1] = cpu_to_be32(PCI0_MEM_SIZE); + qemu_fdt_setprop(fdt, "/pci@c0000000", "reg", cells, 2 * sizeof(cells[0])); + cells[0] = cpu_to_be32(0x01000000); + cells[1] = 0; + cells[2] = 0; + cells[3] = cpu_to_be32(PCI0_IO_BASE); + cells[4] = 0; + cells[5] = cpu_to_be32(PCI0_IO_SIZE); + cells[6] = cpu_to_be32(0x02000000); + cells[7] = 0; + cells[8] = cpu_to_be32(PCI0_MEM_BASE); + cells[9] = cpu_to_be32(PCI0_MEM_BASE); + cells[10] = 0; + cells[11] = cpu_to_be32(PCI0_MEM_SIZE); + qemu_fdt_setprop(fdt, "/pci@c0000000", "ranges", + cells, 12 * sizeof(cells[0])); + qemu_fdt_setprop_cell(fdt, "/pci@c0000000", "#size-cells", 2); + qemu_fdt_setprop_cell(fdt, "/pci@c0000000", "#address-cells", 3); + qemu_fdt_setprop_string(fdt, "/pci@c0000000", "device_type", "pci"); + qemu_fdt_setprop_string(fdt, "/pci@c0000000", "name", "pci"); + + fi.path = "/pci@c0000000"; + pci_bus = mv64361_get_pci_bus(pm->mv, 0); + pci_for_each_device_reverse(pci_bus, 0, add_pci_device, &fi); + + /* pci@80000000 */ + qemu_fdt_add_subnode(fdt, "/pci@80000000"); + cells[0] = 0; + cells[1] = 0; + qemu_fdt_setprop(fdt, "/pci@80000000", "bus-range", + cells, 2 * sizeof(cells[0])); + qemu_fdt_setprop_cell(fdt, "/pci@80000000", "pci-bridge-number", 0); + cells[0] = cpu_to_be32(PCI1_MEM_BASE); + cells[1] = cpu_to_be32(PCI1_MEM_SIZE); + qemu_fdt_setprop(fdt, "/pci@80000000", "reg", cells, 2 * sizeof(cells[0])); + qemu_fdt_setprop_cell(fdt, "/pci@80000000", "8259-interrupt-acknowledge", + 0xf1000cb4); + cells[0] = cpu_to_be32(0x01000000); + cells[1] = 0; + cells[2] = 0; + cells[3] = cpu_to_be32(PCI1_IO_BASE); + cells[4] = 0; + cells[5] = cpu_to_be32(PCI1_IO_SIZE); + cells[6] = cpu_to_be32(0x02000000); + cells[7] = 0; + cells[8] = cpu_to_be32(PCI1_MEM_BASE); + cells[9] = cpu_to_be32(PCI1_MEM_BASE); + cells[10] = 0; + cells[11] = cpu_to_be32(PCI1_MEM_SIZE); + qemu_fdt_setprop(fdt, "/pci@80000000", "ranges", + cells, 12 * sizeof(cells[0])); + qemu_fdt_setprop_cell(fdt, "/pci@80000000", "#size-cells", 2); + qemu_fdt_setprop_cell(fdt, "/pci@80000000", "#address-cells", 3); + qemu_fdt_setprop_string(fdt, "/pci@80000000", "device_type", "pci"); + qemu_fdt_setprop_string(fdt, "/pci@80000000", "name", "pci"); + + fi.path = "/pci@80000000"; + pci_bus = mv64361_get_pci_bus(pm->mv, 1); + pci_for_each_device_reverse(pci_bus, 0, add_pci_device, &fi); + + qemu_fdt_add_subnode(fdt, "/failsafe"); + qemu_fdt_setprop_string(fdt, "/failsafe", "device_type", "serial"); + qemu_fdt_setprop_string(fdt, "/failsafe", "name", "failsafe"); + + /* cpus */ + qemu_fdt_add_subnode(fdt, "/cpus"); + qemu_fdt_setprop_cell(fdt, "/cpus", "#cpus", 1); + qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 1); + qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0); + qemu_fdt_setprop_string(fdt, "/cpus", "name", "cpus"); + + /* FIXME Get CPU name from CPU object */ + const char *cp = "/cpus/PowerPC,G4"; + qemu_fdt_add_subnode(fdt, cp); + qemu_fdt_setprop_cell(fdt, cp, "l2cr", 0); + qemu_fdt_setprop_cell(fdt, cp, "d-cache-size", 0x8000); + qemu_fdt_setprop_cell(fdt, cp, "d-cache-block-size", + cpu->env.dcache_line_size); + qemu_fdt_setprop_cell(fdt, cp, "d-cache-line-size", + cpu->env.dcache_line_size); + qemu_fdt_setprop_cell(fdt, cp, "i-cache-size", 0x8000); + qemu_fdt_setprop_cell(fdt, cp, "i-cache-block-size", + cpu->env.icache_line_size); + qemu_fdt_setprop_cell(fdt, cp, "i-cache-line-size", + cpu->env.icache_line_size); + if (cpu->env.id_tlbs) { + qemu_fdt_setprop_cell(fdt, cp, "i-tlb-sets", cpu->env.nb_ways); + qemu_fdt_setprop_cell(fdt, cp, "i-tlb-size", cpu->env.tlb_per_way); + qemu_fdt_setprop_cell(fdt, cp, "d-tlb-sets", cpu->env.nb_ways); + qemu_fdt_setprop_cell(fdt, cp, "d-tlb-size", cpu->env.tlb_per_way); + qemu_fdt_setprop_string(fdt, cp, "tlb-split", ""); + } + qemu_fdt_setprop_cell(fdt, cp, "tlb-sets", cpu->env.nb_ways); + qemu_fdt_setprop_cell(fdt, cp, "tlb-size", cpu->env.nb_tlb); + qemu_fdt_setprop_string(fdt, cp, "state", "running"); + if (cpu->env.insns_flags & PPC_ALTIVEC) { + qemu_fdt_setprop_string(fdt, cp, "altivec", ""); + qemu_fdt_setprop_string(fdt, cp, "data-streams", ""); + } + /* + * FIXME What flags do data-streams, external-control and + * performance-monitor depend on? + */ + qemu_fdt_setprop_string(fdt, cp, "external-control", ""); + if (cpu->env.insns_flags & PPC_FLOAT_FSQRT) { + qemu_fdt_setprop_string(fdt, cp, "general-purpose", ""); + } + qemu_fdt_setprop_string(fdt, cp, "performance-monitor", ""); + if (cpu->env.insns_flags & PPC_FLOAT_FRES) { + qemu_fdt_setprop_string(fdt, cp, "graphics", ""); + } + qemu_fdt_setprop_cell(fdt, cp, "reservation-granule-size", 4); + qemu_fdt_setprop_cell(fdt, cp, "timebase-frequency", + cpu->env.tb_env->tb_freq); + qemu_fdt_setprop_cell(fdt, cp, "bus-frequency", BUS_FREQ_HZ); + qemu_fdt_setprop_cell(fdt, cp, "clock-frequency", BUS_FREQ_HZ * 7.5); + qemu_fdt_setprop_cell(fdt, cp, "cpu-version", cpu->env.spr[SPR_PVR]); + cells[0] = 0; + cells[1] = 0; + qemu_fdt_setprop(fdt, cp, "reg", cells, 2 * sizeof(cells[0])); + qemu_fdt_setprop_string(fdt, cp, "device_type", "cpu"); + qemu_fdt_setprop_string(fdt, cp, "name", strrchr(cp, '/') + 1); + + /* memory */ + qemu_fdt_add_subnode(fdt, "/memory@0"); + cells[0] = 0; + cells[1] = cpu_to_be32(machine->ram_size); + qemu_fdt_setprop(fdt, "/memory@0", "reg", cells, 2 * sizeof(cells[0])); + qemu_fdt_setprop_string(fdt, "/memory@0", "device_type", "memory"); + qemu_fdt_setprop_string(fdt, "/memory@0", "name", "memory"); + + qemu_fdt_add_subnode(fdt, "/chosen"); + qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", + machine->kernel_cmdline ?: ""); + qemu_fdt_setprop_string(fdt, "/chosen", "name", "chosen"); + + qemu_fdt_add_subnode(fdt, "/openprom"); + qemu_fdt_setprop_string(fdt, "/openprom", "model", "Pegasos2,1.1"); + + return fdt; +} From patchwork Fri Jul 9 05:17:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366759 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.8 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 506E3C07E99 for ; Fri, 9 Jul 2021 05:42:56 +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 C343B61447 for ; Fri, 9 Jul 2021 05:42:55 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C343B61447 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:47498 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jHq-0005ng-TA for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:42:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35464) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuG-0002Pe-4Q; Fri, 09 Jul 2021 01:18:32 -0400 Received: from ozlabs.org ([2401:3900:2:1::2]:56113) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iu9-00025C-HX; Fri, 09 Jul 2021 01:18:31 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf5Zgmz9t8j; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=FS0CXh5tr8em9jVtL2JvYY6xzmNt7xn81MDXwdvg4jI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bp4CMN9YWO95EDntamYVEB+ptAkX1bf/efkJk9cdYoI9hkkDovkcs81dRYHVSynvf I3KcQZCqUpT8Wx1/MffTfeQAMb4/dq8NJwL6xitsnCaV9h305Oi8jkFoTMw9ia8Cg3 gTtSO6plywaH6OD/Bkpc1TnpoGWt1mef3rCF/qFw= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 28/33] ppc/pegasos2: Fix use of && instead of & Date: Fri, 9 Jul 2021 15:17:23 +1000 Message-Id: <20210709051728.170203-29-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This is obviously intended to be a mask, not a logical operation. Signed-off-by: David Gibson --- hw/ppc/pegasos2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index f1741a4512..cf1dc53c83 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -584,7 +584,7 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque) pci_get_word(&d->config[PCI_SUBSYSTEM_VENDOR_ID])); cells[0] = pci_get_long(&d->config[PCI_CLASS_REVISION]); qemu_fdt_setprop_cell(fi->fdt, node->str, "class-code", cells[0] >> 8); - qemu_fdt_setprop_cell(fi->fdt, node->str, "revision-id", cells[0] && 0xff); + qemu_fdt_setprop_cell(fi->fdt, node->str, "revision-id", cells[0] & 0xff); qemu_fdt_setprop_cell(fi->fdt, node->str, "device-id", pci_get_word(&d->config[PCI_DEVICE_ID])); qemu_fdt_setprop_cell(fi->fdt, node->str, "vendor-id", From patchwork Fri Jul 9 05:17:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366775 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.8 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 DA8D3C07E99 for ; Fri, 9 Jul 2021 05:52:02 +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 939C861441 for ; Fri, 9 Jul 2021 05:52:02 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 939C861441 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:43710 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jQf-0005Mc-Mz for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:52:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35516) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuM-0002cw-TD; Fri, 09 Jul 2021 01:18:39 -0400 Received: from ozlabs.org ([203.11.71.1]:56681) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iu9-00025L-LX; Fri, 09 Jul 2021 01:18:38 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf5xLvz9t9b; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=0wVnwfa6ea8GVwzKdrAxx1mR1Zr6PkQYevmrq27QpMQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UIjwMosAFUXh66AkgMfLpOUEs2OivXQNhG+0+nd2sfsxgkVi2lSlNIJdh5TvIEeyJ qtLIJ3w6VtpCzR4j0LlwpRdlmVadbxnaqtPzfxNBzm/KwPF7lhVFyxHVd0YiEIBZA8 aLpBprUe7GDLScXM0EWk5QWXWrqhTTv33afoBg+g= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 29/33] ppc/pegasos2: Implement some RTAS functions with VOF Date: Fri, 9 Jul 2021 15:17:24 +1000 Message-Id: <20210709051728.170203-30-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable 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: aik@ozlabs.ru, David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: BALATON Zoltan Linux uses RTAS functions to access PCI devices so we need to provide these with VOF. Implement some of the most important functions to allow booting Linux with VOF. With this the board is now usable without a binary ROM image and we can enable it by default as other boards. Signed-off-by: BALATON Zoltan Message-Id: <20210708215113.B3F747456E3@zero.eik.bme.hu> Signed-off-by: David Gibson --- default-configs/devices/ppc-softmmu.mak | 2 +- hw/ppc/pegasos2.c | 137 ++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) diff --git a/default-configs/devices/ppc-softmmu.mak b/default-configs/devices/ppc-softmmu.mak index c2d41198cd..4535993d8d 100644 --- a/default-configs/devices/ppc-softmmu.mak +++ b/default-configs/devices/ppc-softmmu.mak @@ -14,7 +14,7 @@ CONFIG_SAM460EX=y CONFIG_MAC_OLDWORLD=y CONFIG_MAC_NEWWORLD=y -CONFIG_PEGASOS2=n +CONFIG_PEGASOS2=y # For PReP CONFIG_PREP=y diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index cf1dc53c83..9a6ae867e4 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -43,6 +43,7 @@ #define PROM_SIZE 0x80000 #define KVMPPC_HCALL_BASE 0xf000 +#define KVMPPC_H_RTAS (KVMPPC_HCALL_BASE + 0x0) #define KVMPPC_H_VOF_CLIENT (KVMPPC_HCALL_BASE + 0x5) #define H_SUCCESS 0 @@ -195,6 +196,30 @@ static void pegasos2_init(MachineState *machine) } } +static uint32_t pegasos2_pci_config_read(AddressSpace *as, int bus, + uint32_t addr, uint32_t len) +{ + hwaddr pcicfg = (bus ? 0xf1000c78 : 0xf1000cf8); + uint32_t val = 0xffffffff; + + stl_le_phys(as, pcicfg, addr | BIT(31)); + switch (len) { + case 4: + val = ldl_le_phys(as, pcicfg + 4); + break; + case 2: + val = lduw_le_phys(as, pcicfg + 4); + break; + case 1: + val = ldub_phys(as, pcicfg + 4); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid length\n", __func__); + break; + } + return val; +} + static void pegasos2_pci_config_write(AddressSpace *as, int bus, uint32_t addr, uint32_t len, uint32_t val) { @@ -304,6 +329,87 @@ static void pegasos2_machine_reset(MachineState *machine) pm->cpu->vhyp = PPC_VIRTUAL_HYPERVISOR(machine); } +enum pegasos2_rtas_tokens { + RTAS_RESTART_RTAS = 0, + RTAS_NVRAM_FETCH = 1, + RTAS_NVRAM_STORE = 2, + RTAS_GET_TIME_OF_DAY = 3, + RTAS_SET_TIME_OF_DAY = 4, + RTAS_EVENT_SCAN = 6, + RTAS_CHECK_EXCEPTION = 7, + RTAS_READ_PCI_CONFIG = 8, + RTAS_WRITE_PCI_CONFIG = 9, + RTAS_DISPLAY_CHARACTER = 10, + RTAS_SET_INDICATOR = 11, + RTAS_POWER_OFF = 17, + RTAS_SUSPEND = 18, + RTAS_HIBERNATE = 19, + RTAS_SYSTEM_REBOOT = 20, +}; + +static target_ulong pegasos2_rtas(PowerPCCPU *cpu, Pegasos2MachineState *pm, + target_ulong args_real) +{ + AddressSpace *as = CPU(cpu)->as; + uint32_t token = ldl_be_phys(as, args_real); + uint32_t nargs = ldl_be_phys(as, args_real + 4); + uint32_t nrets = ldl_be_phys(as, args_real + 8); + uint32_t args = args_real + 12; + uint32_t rets = args_real + 12 + nargs * 4; + + if (nrets < 1) { + qemu_log_mask(LOG_GUEST_ERROR, "Too few return values in RTAS call\n"); + return H_PARAMETER; + } + switch (token) { + case RTAS_READ_PCI_CONFIG: + { + uint32_t addr, len, val; + + if (nargs != 2 || nrets != 2) { + stl_be_phys(as, rets, -1); + return H_PARAMETER; + } + addr = ldl_be_phys(as, args); + len = ldl_be_phys(as, args + 4); + val = pegasos2_pci_config_read(as, !(addr >> 24), + addr & 0x0fffffff, len); + stl_be_phys(as, rets, 0); + stl_be_phys(as, rets + 4, val); + return H_SUCCESS; + } + case RTAS_WRITE_PCI_CONFIG: + { + uint32_t addr, len, val; + + if (nargs != 3 || nrets != 1) { + stl_be_phys(as, rets, -1); + return H_PARAMETER; + } + addr = ldl_be_phys(as, args); + len = ldl_be_phys(as, args + 4); + val = ldl_be_phys(as, args + 8); + pegasos2_pci_config_write(as, !(addr >> 24), + addr & 0x0fffffff, len, val); + stl_be_phys(as, rets, 0); + return H_SUCCESS; + } + case RTAS_DISPLAY_CHARACTER: + if (nargs != 1 || nrets != 1) { + stl_be_phys(as, rets, -1); + return H_PARAMETER; + } + qemu_log_mask(LOG_UNIMP, "%c", ldl_be_phys(as, args)); + stl_be_phys(as, rets, 0); + return H_SUCCESS; + default: + qemu_log_mask(LOG_UNIMP, "Unknown RTAS token %u (args=%u, rets=%u)\n", + token, nargs, nrets); + stl_be_phys(as, rets, 0); + return H_SUCCESS; + } +} + static void pegasos2_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) { Pegasos2MachineState *pm = PEGASOS2_MACHINE(vhyp); @@ -315,6 +421,8 @@ static void pegasos2_hypercall(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) if (msr_pr) { qemu_log_mask(LOG_GUEST_ERROR, "Hypercall made with MSR[PR]=1\n"); env->gpr[3] = H_PRIVILEGE; + } else if (env->gpr[3] == KVMPPC_H_RTAS) { + env->gpr[3] = pegasos2_rtas(cpu, pm, env->gpr[4]); } else if (env->gpr[3] == KVMPPC_H_VOF_CLIENT) { int ret = vof_client_call(MACHINE(pm), pm->vof, pm->fdt_blob, env->gpr[4]); @@ -687,6 +795,35 @@ static void *build_fdt(MachineState *machine, int *fdt_size) qemu_fdt_setprop_string(fdt, "/failsafe", "device_type", "serial"); qemu_fdt_setprop_string(fdt, "/failsafe", "name", "failsafe"); + qemu_fdt_add_subnode(fdt, "/rtas"); + qemu_fdt_setprop_cell(fdt, "/rtas", "system-reboot", RTAS_SYSTEM_REBOOT); + qemu_fdt_setprop_cell(fdt, "/rtas", "hibernate", RTAS_HIBERNATE); + qemu_fdt_setprop_cell(fdt, "/rtas", "suspend", RTAS_SUSPEND); + qemu_fdt_setprop_cell(fdt, "/rtas", "power-off", RTAS_POWER_OFF); + qemu_fdt_setprop_cell(fdt, "/rtas", "set-indicator", RTAS_SET_INDICATOR); + qemu_fdt_setprop_cell(fdt, "/rtas", "display-character", + RTAS_DISPLAY_CHARACTER); + qemu_fdt_setprop_cell(fdt, "/rtas", "write-pci-config", + RTAS_WRITE_PCI_CONFIG); + qemu_fdt_setprop_cell(fdt, "/rtas", "read-pci-config", + RTAS_READ_PCI_CONFIG); + /* Pegasos2 firmware misspells check-exception and guests use that */ + qemu_fdt_setprop_cell(fdt, "/rtas", "check-execption", + RTAS_CHECK_EXCEPTION); + qemu_fdt_setprop_cell(fdt, "/rtas", "event-scan", RTAS_EVENT_SCAN); + qemu_fdt_setprop_cell(fdt, "/rtas", "set-time-of-day", + RTAS_SET_TIME_OF_DAY); + qemu_fdt_setprop_cell(fdt, "/rtas", "get-time-of-day", + RTAS_GET_TIME_OF_DAY); + qemu_fdt_setprop_cell(fdt, "/rtas", "nvram-store", RTAS_NVRAM_STORE); + qemu_fdt_setprop_cell(fdt, "/rtas", "nvram-fetch", RTAS_NVRAM_FETCH); + qemu_fdt_setprop_cell(fdt, "/rtas", "restart-rtas", RTAS_RESTART_RTAS); + qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-error-log-max", 0); + qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-event-scan-rate", 0); + qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-display-device", 0); + qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-size", 20); + qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-version", 1); + /* cpus */ qemu_fdt_add_subnode(fdt, "/cpus"); qemu_fdt_setprop_cell(fdt, "/cpus", "#cpus", 1); From patchwork Fri Jul 9 05:17:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366749 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.8 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 EE54EC07E99 for ; Fri, 9 Jul 2021 05:36:07 +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 74E8861433 for ; Fri, 9 Jul 2021 05:36:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 74E8861433 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:35116 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jBF-0005f7-J2 for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:36:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35504) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuK-0002ZR-Kv; Fri, 09 Jul 2021 01:18:37 -0400 Received: from ozlabs.org ([203.11.71.1]:38859) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuC-00026n-K1; Fri, 09 Jul 2021 01:18:36 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHf6f1qz9t9y; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807854; bh=IW1b31ozhZIG/pyqRQtJdVZq/uJD6DiefOWaqIQiPfM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HGxwqIFagZgC/YYM1tajQ2dNn1Iw32R5foXVTg8Yat6HZRkNlUj8QNRpd2Viiaflx W5UevklKMw1oqyAG9k1k6ebDMxmgUsDYgzZGNb6qQPfDwawZavZd5rJSU9Mg7OkywH QSucwyxASxbh3Uh0LNpV8690mFwTw71ZqjpVVuUg= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 30/33] target/ppc: Don't compile ppc_tlb_invalid_all without TCG Date: Fri, 9 Jul 2021 15:17:25 +1000 Message-Id: <20210709051728.170203-31-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, "Lucas Mateus Castro \(alqotel\)" , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: "Lucas Mateus Castro (alqotel)" The function ppc_tlb_invalid_all is not compiled anymore in a TCG-less environment, and the call to that function has been disabled in this situation Signed-off-by: Lucas Mateus Castro (alqotel) Message-Id: <20210708164957.28096-2-lucas.araujo@eldorado.org.br> Signed-off-by: David Gibson --- target/ppc/cpu_init.c | 2 ++ target/ppc/mmu_helper.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 6f8ce010ba..505a0ed6ac 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -8847,9 +8847,11 @@ static void ppc_cpu_reset(DeviceState *dev) #if !defined(CONFIG_USER_ONLY) env->nip = env->hreset_vector | env->excp_prefix; +#if defined(CONFIG_TCG) if (env->mmu_model != POWERPC_MMU_REAL) { ppc_tlb_invalidate_all(env); } +#endif /* CONFIG_TCG */ #endif hreg_compute_hflags(env); diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 47e9f9529e..869d24d301 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -825,6 +825,7 @@ static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, return ret; } +#ifdef CONFIG_TCG static void booke206_flush_tlb(CPUPPCState *env, int flags, const int check_iprot) { @@ -846,6 +847,7 @@ static void booke206_flush_tlb(CPUPPCState *env, int flags, tlb_flush(env_cpu(env)); } +#endif static hwaddr booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb) @@ -1901,6 +1903,7 @@ void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value) } #endif +#ifdef CONFIG_TCG /*****************************************************************************/ /* TLB management */ void ppc_tlb_invalidate_all(CPUPPCState *env) @@ -1944,6 +1947,7 @@ void ppc_tlb_invalidate_all(CPUPPCState *env) break; } } +#endif #ifdef CONFIG_TCG void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr) From patchwork Fri Jul 9 05:17:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366777 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=-15.1 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,URIBL_BLACK,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 5A2BEC07E99 for ; Fri, 9 Jul 2021 05:56:01 +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 D90A461448 for ; Fri, 9 Jul 2021 05:56:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D90A461448 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:56732 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jUV-00065l-V1 for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:56:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35610) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iub-0003Kh-Vd; Fri, 09 Jul 2021 01:18:54 -0400 Received: from ozlabs.org ([2401:3900:2:1::2]:51591) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuZ-0002H6-8h; Fri, 09 Jul 2021 01:18:53 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHg0SLwz9tD3; Fri, 9 Jul 2021 15:17:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807855; bh=cTi5yDJKQULjieGYC6iZ9jm+AbVbWDmYf3ZIe5affSo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fidNcqLQlPc7YrdsERdUOkzj53NgtGJJgRfLI58nNcVBgHJcXLdAOuLZu9/OCuVye Y6mKazi318Ev83IsQHnw8IZe1Q1s/LSfpAO2pUgYAE6O7Zyzszo5TUS7GFjxFxtfz4 mSRJDlgn2Apu0Nfz/ShKvcdFMssoHX/PMl+21Q7o= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 31/33] spapr: Fix implementation of Open Firmware client interface Date: Fri, 9 Jul 2021 15:17:26 +1000 Message-Id: <20210709051728.170203-32-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=2401:3900:2:1::2; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_PASS=-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: aik@ozlabs.ru, David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Alexey Kardashevskiy This addresses the comments from v22. The functional changes are (the VOF ones need retesting with Pegasos2): (VOF) setprop will start failing if the machine class callback did not handle it; (VOF) unit addresses are lowered in path_offset(); (SPAPR) /chosen/bootargs is initialized from kernel_cmdline if the client did not change it. Fixes: 5c991e5d4378 ("spapr: Implement Open Firmware client interface") Cc: BALATON Zoltan Signed-off-by: Alexey Kardashevskiy Message-Id: <20210708065625.548396-1-aik@ozlabs.ru> Tested-by: BALATON Zoltan Signed-off-by: David Gibson --- MAINTAINERS | 4 ++-- hw/ppc/spapr.c | 10 +--------- hw/ppc/spapr_hcall.c | 5 ++--- hw/ppc/spapr_vof.c | 32 +++++++++++++++++++++++--------- hw/ppc/vof.c | 30 +++++++++++++++++------------- include/hw/ppc/spapr.h | 3 +-- pc-bios/vof.bin | Bin 3784 -> 3456 bytes pc-bios/vof/ci.c | 2 +- pc-bios/vof/libc.c | 26 -------------------------- pc-bios/vof/main.c | 2 +- pc-bios/vof/vof.h | 2 -- 11 files changed, 48 insertions(+), 68 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index ce122eeced..89d71b42b2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1362,8 +1362,8 @@ F: include/hw/pci-host/mv64361.h Virtual Open Firmware (VOF) M: Alexey Kardashevskiy -M: David Gibson -M: Greg Kurz +R: David Gibson +R: Greg Kurz L: qemu-ppc@nongnu.org S: Maintained F: hw/ppc/spapr_vof* diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index e9b6d0f587..3808d47053 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1645,15 +1645,7 @@ static void spapr_machine_reset(MachineState *machine) fdt = spapr_build_fdt(spapr, true, FDT_MAX_SIZE); if (spapr->vof) { - target_ulong stack_ptr = 0; - - spapr_vof_reset(spapr, fdt, &stack_ptr, &error_fatal); - - spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, - stack_ptr, spapr->initrd_base, - spapr->initrd_size); - /* VOF is 32bit BE so enforce MSR here */ - first_ppc_cpu->env.msr &= ~((1ULL << MSR_SF) | (1ULL << MSR_LE)); + spapr_vof_reset(spapr, fdt, &error_fatal); /* * Do not pack the FDT as the client may change properties. * VOF client does not expect the FDT so we do not load it to the VM. diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 80ae8eaadd..0e9a5b2e40 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1080,7 +1080,7 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu, SpaprOptionVector *ov1_guest, *ov5_guest; bool guest_radix; bool raw_mode_supported = false; - bool guest_xive, reset_fdt = false; + bool guest_xive; CPUState *cs; void *fdt; uint32_t max_compat = spapr->max_compat_pvr; @@ -1233,8 +1233,7 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu, spapr_setup_hpt(spapr); } - reset_fdt = spapr->vof != NULL; - fdt = spapr_build_fdt(spapr, reset_fdt, fdt_bufsize); + fdt = spapr_build_fdt(spapr, spapr->vof != NULL, fdt_bufsize); g_free(spapr->fdt_blob); spapr->fdt_size = fdt_totalsize(fdt); spapr->fdt_initial_size = spapr->fdt_size; diff --git a/hw/ppc/spapr_vof.c b/hw/ppc/spapr_vof.c index 131a03fec0..40ce8fe003 100644 --- a/hw/ppc/spapr_vof.c +++ b/hw/ppc/spapr_vof.c @@ -8,6 +8,7 @@ #include "qapi/error.h" #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" +#include "hw/ppc/spapr_cpu_core.h" #include "hw/ppc/fdt.h" #include "hw/ppc/vof.h" #include "sysemu/sysemu.h" @@ -29,13 +30,19 @@ target_ulong spapr_h_vof_client(PowerPCCPU *cpu, SpaprMachineState *spapr, void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt) { char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); - int chosen; vof_build_dt(fdt, spapr->vof); - _FDT(chosen = fdt_path_offset(fdt, "/chosen")); - _FDT(fdt_setprop_string(fdt, chosen, "bootargs", - spapr->vof->bootargs ? : "")); + if (spapr->vof->bootargs) { + int chosen; + + _FDT(chosen = fdt_path_offset(fdt, "/chosen")); + /* + * If the client did not change "bootargs", spapr_dt_chosen() must have + * stored machine->kernel_cmdline in it before getting here. + */ + _FDT(fdt_setprop_string(fdt, chosen, "bootargs", spapr->vof->bootargs)); + } /* * SLOF-less setup requires an open instance of stdout for early @@ -48,20 +55,21 @@ void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt) } } -void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, - target_ulong *stack_ptr, Error **errp) +void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, Error **errp) { + target_ulong stack_ptr; Vof *vof = spapr->vof; + PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); vof_init(vof, spapr->rma_size, errp); - *stack_ptr = vof_claim(vof, 0, VOF_STACK_SIZE, VOF_STACK_SIZE); - if (*stack_ptr == -1) { + stack_ptr = vof_claim(vof, 0, VOF_STACK_SIZE, VOF_STACK_SIZE); + if (stack_ptr == -1) { error_setg(errp, "Memory allocation for stack failed"); return; } /* Stack grows downwards plus reserve space for the minimum stack frame */ - *stack_ptr += VOF_STACK_SIZE - 0x20; + stack_ptr += VOF_STACK_SIZE - 0x20; if (spapr->kernel_size && vof_claim(vof, spapr->kernel_addr, spapr->kernel_size, 0) == -1) { @@ -77,6 +85,12 @@ void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, spapr_vof_client_dt_finalize(spapr, fdt); + spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT, + stack_ptr, spapr->initrd_base, + spapr->initrd_size); + /* VOF is 32bit BE so enforce MSR here */ + first_ppc_cpu->env.msr &= ~((1ULL << MSR_SF) | (1ULL << MSR_LE)); + /* * At this point the expected allocation map is: * diff --git a/hw/ppc/vof.c b/hw/ppc/vof.c index 47c86e394e..81f6596215 100644 --- a/hw/ppc/vof.c +++ b/hw/ppc/vof.c @@ -144,15 +144,16 @@ static int path_offset(const void *fdt, const char *path) * the lower case forms of the hexadecimal digits in the range a..f, * suppressing leading zeros". */ - at = strchr(path, '@'); - if (!at) { - return fdt_path_offset(fdt, path); - } - p = g_strdup(path); - for (at = at - path + p + 1; *at; ++at) { - *at = tolower(*at); + for (at = strchr(p, '@'); at && *at; ) { + if (*at == '/') { + at = strchr(at, '@'); + } else { + *at = tolower(*at); + ++at; + } } + return fdt_path_offset(fdt, p); } @@ -300,6 +301,7 @@ static uint32_t vof_setprop(MachineState *ms, void *fdt, Vof *vof, char trval[64] = ""; char nodepath[VOF_MAX_PATH] = ""; Object *vmo = object_dynamic_cast(OBJECT(ms), TYPE_VOF_MACHINE_IF); + VofMachineIfClass *vmc; g_autofree char *val = NULL; if (vallen > VOF_MAX_SETPROPLEN) { @@ -322,13 +324,13 @@ static uint32_t vof_setprop(MachineState *ms, void *fdt, Vof *vof, goto trace_exit; } - if (vmo) { - VofMachineIfClass *vmc = VOF_MACHINE_GET_CLASS(vmo); + if (!vmo) { + goto trace_exit; + } - if (vmc->setprop && - !vmc->setprop(ms, nodepath, propname, val, vallen)) { - goto trace_exit; - } + vmc = VOF_MACHINE_GET_CLASS(vmo); + if (!vmc->setprop || !vmc->setprop(ms, nodepath, propname, val, vallen)) { + goto trace_exit; } ret = fdt_setprop(fdt, offset, propname, val, vallen); @@ -919,6 +921,8 @@ static uint32_t vof_client_handle(MachineState *ms, void *fdt, Vof *vof, ret = -1; } +#undef cmpserv + return ret; } diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index a25e69fe4c..779f707fb8 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -964,8 +964,7 @@ void spapr_set_all_lpcrs(target_ulong value, target_ulong mask); hwaddr spapr_get_rtas_addr(void); bool spapr_memory_hot_unplug_supported(SpaprMachineState *spapr); -void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, - target_ulong *stack_ptr, Error **errp); +void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, Error **errp); void spapr_vof_quiesce(MachineState *ms); bool spapr_vof_setprop(MachineState *ms, const char *path, const char *propname, void *val, int vallen); diff --git a/pc-bios/vof.bin b/pc-bios/vof.bin index 1ec670be82134adcb5ae128732aff6e371281360..300cb7c7f9d9d77ffa7cbb7f0f26919246ef2d14 100755 GIT binary patch delta 151 zcmX>h+aSGxjghy9!GnR}jEw^WLxNM!WMRf~rtUM7dl>VWx??8)VQgaRda${HDTtA& zvuE-Z<}9X8h0P8uhZvdKVH uz%*HauS<{T1Oo%l10a6Gz`)A@#2gF^j0r&O17wQ;u?!Gv0I>lOTL1tL)F-q6 delta 369 zcmZpWJ|Vk-jghyH!GnR}jEw^WLxNM^WMRf~re2ZBJ&buwJxeD4VQgaR(b(L;6vW8X zb!GAu<}9YJjLi-#hZvbUmP}@0i(~3=nViCw#?*di@)@=|ruK%-KI~hW>f;$?8toY* zYPdWc92yuV0NDzSK(SgaFA*RO7I$o9r~rvuYX1KZ5(CLiv}fQz5(BFTit$(~FfagV z0iZ(-fNFUxwf_GHi38PgSaJf{@(diEUJMK~JsB8)VgeSHnhcB}4M4>LAOnF8VQ_5t ze*$Pg43IAYlml5L12P2J@X0?olqCgl>7J~^X|b7u>j2Y40hP%oc)IlX1Q;0jG=SIy dh=FGF1u!r$CIGPykR1cWDL`BR#1%l?005cvU&jCd diff --git a/pc-bios/vof/ci.c b/pc-bios/vof/ci.c index 2b56050238..fc4821b3e9 100644 --- a/pc-bios/vof/ci.c +++ b/pc-bios/vof/ci.c @@ -69,7 +69,7 @@ static int call_ci(const char *service, int nargs, int nret, ...) } if (ci_entry((uint32_t)(&args)) < 0) { - return PROM_ERROR; + return -1; } return (nret > 0) ? args.args[nargs] : 0; diff --git a/pc-bios/vof/libc.c b/pc-bios/vof/libc.c index 00c10e6e7d..fdbc30f777 100644 --- a/pc-bios/vof/libc.c +++ b/pc-bios/vof/libc.c @@ -54,32 +54,6 @@ int memcmp(const void *ptr1, const void *ptr2, size_t n) return 0; } -void *memmove(void *dest, const void *src, size_t n) -{ - char *cdest; - const char *csrc; - int i; - - /* Do the buffers overlap in a bad way? */ - if (src < dest && src + n >= dest) { - /* Copy from end to start */ - cdest = dest + n - 1; - csrc = src + n - 1; - for (i = 0; i < n; i++) { - *cdest-- = *csrc--; - } - } else { - /* Normal copy is possible */ - cdest = dest; - csrc = src; - for (i = 0; i < n; i++) { - *cdest++ = *csrc++; - } - } - - return dest; -} - void *memset(void *dest, int c, size_t size) { unsigned char *d = (unsigned char *)dest; diff --git a/pc-bios/vof/main.c b/pc-bios/vof/main.c index 9fc30d2d09..0f0f6b4cb1 100644 --- a/pc-bios/vof/main.c +++ b/pc-bios/vof/main.c @@ -6,7 +6,7 @@ void do_boot(unsigned long addr, unsigned long _r3, unsigned long _r4) register unsigned long r4 __asm__("r4") = _r4; register unsigned long r5 __asm__("r5") = (unsigned long) _prom_entry; - ((client *)(uint32_t)addr)(); + ((void (*)(void))(uint32_t)addr)(); } void entry_c(void) diff --git a/pc-bios/vof/vof.h b/pc-bios/vof/vof.h index 2d89580769..5f12c077f5 100644 --- a/pc-bios/vof/vof.h +++ b/pc-bios/vof/vof.h @@ -10,11 +10,9 @@ typedef unsigned short uint16_t; typedef unsigned long uint32_t; typedef unsigned long long uint64_t; #define NULL (0) -#define PROM_ERROR (-1u) typedef unsigned long ihandle; typedef unsigned long phandle; typedef int size_t; -typedef void client(void); /* globals */ extern void _prom_entry(void); /* OF CI entry point (i.e. this firmware) */ From patchwork Fri Jul 9 05:17:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366767 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=-21.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,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 AD183C07E99 for ; Fri, 9 Jul 2021 05:48:28 +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 2EB4761442 for ; Fri, 9 Jul 2021 05:48:28 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2EB4761442 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:60074 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jND-0005uD-9E for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:48:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35528) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuN-0002d0-S5; Fri, 09 Jul 2021 01:18:39 -0400 Received: from ozlabs.org ([203.11.71.1]:46467) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuG-0002IW-Db; Fri, 09 Jul 2021 01:18:39 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHg0p44z9tD4; Fri, 9 Jul 2021 15:17:35 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807855; bh=myEtZ8xVZJYy39NGlcIVY++ImWOqWlbh/fOS5DU2whk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gEyMJtAxhcy4djTVQwiytYzDM59U5qQbaCV/grfWj4O0WuSyRIrt2SVrydmfVMosB zuKZR3WggqS6Ph6s6SUoZS3FXzZYNwfILLVadcQfvI0WJQPFa0vYN0/BTVsdthhAXD 7C1V8wP8pHnhVygQ0DnBef+YRQtW5086DJAkjYlg= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 32/33] linux-headers: Update Date: Fri, 9 Jul 2021 15:17:27 +1000 Message-Id: <20210709051728.170203-33-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, Bharata B Rao Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Bharata B Rao Update to mainline commit: 79160a603bdb ("Merge tag 'usb-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb" Signed-off-by: Bharata B Rao Message-Id: <20210706112440.1449562-2-bharata@linux.ibm.com> Signed-off-by: David Gibson --- include/standard-headers/asm-x86/kvm_para.h | 13 +++ include/standard-headers/drm/drm_fourcc.h | 7 ++ include/standard-headers/linux/ethtool.h | 4 +- .../linux/input-event-codes.h | 1 + include/standard-headers/linux/virtio_ids.h | 2 +- include/standard-headers/linux/virtio_vsock.h | 9 ++ linux-headers/asm-arm64/kvm.h | 11 ++ linux-headers/asm-generic/mman-common.h | 3 + linux-headers/asm-generic/unistd.h | 4 +- linux-headers/asm-mips/mman.h | 3 + linux-headers/asm-mips/unistd_n32.h | 1 + linux-headers/asm-mips/unistd_n64.h | 1 + linux-headers/asm-mips/unistd_o32.h | 1 + linux-headers/asm-powerpc/unistd_32.h | 1 + linux-headers/asm-powerpc/unistd_64.h | 1 + linux-headers/asm-s390/unistd_32.h | 1 + linux-headers/asm-s390/unistd_64.h | 1 + linux-headers/asm-x86/kvm.h | 13 +++ linux-headers/asm-x86/unistd_32.h | 7 +- linux-headers/asm-x86/unistd_64.h | 7 +- linux-headers/asm-x86/unistd_x32.h | 7 +- linux-headers/linux/kvm.h | 105 ++++++++++++++++++ linux-headers/linux/userfaultfd.h | 11 +- 23 files changed, 197 insertions(+), 17 deletions(-) diff --git a/include/standard-headers/asm-x86/kvm_para.h b/include/standard-headers/asm-x86/kvm_para.h index 215d01b4ec..204cfb8640 100644 --- a/include/standard-headers/asm-x86/kvm_para.h +++ b/include/standard-headers/asm-x86/kvm_para.h @@ -33,6 +33,8 @@ #define KVM_FEATURE_PV_SCHED_YIELD 13 #define KVM_FEATURE_ASYNC_PF_INT 14 #define KVM_FEATURE_MSI_EXT_DEST_ID 15 +#define KVM_FEATURE_HC_MAP_GPA_RANGE 16 +#define KVM_FEATURE_MIGRATION_CONTROL 17 #define KVM_HINTS_REALTIME 0 @@ -54,6 +56,7 @@ #define MSR_KVM_POLL_CONTROL 0x4b564d05 #define MSR_KVM_ASYNC_PF_INT 0x4b564d06 #define MSR_KVM_ASYNC_PF_ACK 0x4b564d07 +#define MSR_KVM_MIGRATION_CONTROL 0x4b564d08 struct kvm_steal_time { uint64_t steal; @@ -90,6 +93,16 @@ struct kvm_clock_pairing { /* MSR_KVM_ASYNC_PF_INT */ #define KVM_ASYNC_PF_VEC_MASK GENMASK(7, 0) +/* MSR_KVM_MIGRATION_CONTROL */ +#define KVM_MIGRATION_READY (1 << 0) + +/* KVM_HC_MAP_GPA_RANGE */ +#define KVM_MAP_GPA_RANGE_PAGE_SZ_4K 0 +#define KVM_MAP_GPA_RANGE_PAGE_SZ_2M (1 << 0) +#define KVM_MAP_GPA_RANGE_PAGE_SZ_1G (1 << 1) +#define KVM_MAP_GPA_RANGE_ENC_STAT(n) (n << 4) +#define KVM_MAP_GPA_RANGE_ENCRYPTED KVM_MAP_GPA_RANGE_ENC_STAT(1) +#define KVM_MAP_GPA_RANGE_DECRYPTED KVM_MAP_GPA_RANGE_ENC_STAT(0) /* Operations for KVM_HC_MMU_OP */ #define KVM_MMU_OP_WRITE_PTE 1 diff --git a/include/standard-headers/drm/drm_fourcc.h b/include/standard-headers/drm/drm_fourcc.h index a61ae520c2..352b51fd0a 100644 --- a/include/standard-headers/drm/drm_fourcc.h +++ b/include/standard-headers/drm/drm_fourcc.h @@ -167,6 +167,13 @@ extern "C" { #define DRM_FORMAT_RGBA1010102 fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */ #define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */ +/* 64 bpp RGB */ +#define DRM_FORMAT_XRGB16161616 fourcc_code('X', 'R', '4', '8') /* [63:0] x:R:G:B 16:16:16:16 little endian */ +#define DRM_FORMAT_XBGR16161616 fourcc_code('X', 'B', '4', '8') /* [63:0] x:B:G:R 16:16:16:16 little endian */ + +#define DRM_FORMAT_ARGB16161616 fourcc_code('A', 'R', '4', '8') /* [63:0] A:R:G:B 16:16:16:16 little endian */ +#define DRM_FORMAT_ABGR16161616 fourcc_code('A', 'B', '4', '8') /* [63:0] A:B:G:R 16:16:16:16 little endian */ + /* * Floating point 64bpp RGB * IEEE 754-2008 binary16 half-precision float diff --git a/include/standard-headers/linux/ethtool.h b/include/standard-headers/linux/ethtool.h index 218d944a17..053d3fafdf 100644 --- a/include/standard-headers/linux/ethtool.h +++ b/include/standard-headers/linux/ethtool.h @@ -233,7 +233,7 @@ enum tunable_id { ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */ /* * Add your fresh new tunable attribute above and remember to update - * tunable_strings[] in net/core/ethtool.c + * tunable_strings[] in net/ethtool/common.c */ __ETHTOOL_TUNABLE_COUNT, }; @@ -297,7 +297,7 @@ enum phy_tunable_id { ETHTOOL_PHY_EDPD, /* * Add your fresh new phy tunable attribute above and remember to update - * phy_tunable_strings[] in net/core/ethtool.c + * phy_tunable_strings[] in net/ethtool/common.c */ __ETHTOOL_PHY_TUNABLE_COUNT, }; diff --git a/include/standard-headers/linux/input-event-codes.h b/include/standard-headers/linux/input-event-codes.h index c403b9cb0d..b5e86b40ab 100644 --- a/include/standard-headers/linux/input-event-codes.h +++ b/include/standard-headers/linux/input-event-codes.h @@ -611,6 +611,7 @@ #define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */ #define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */ #define KEY_KBD_LAYOUT_NEXT 0x248 /* AC Next Keyboard Layout Select */ +#define KEY_EMOJI_PICKER 0x249 /* Show/hide emoji picker (HUTRR101) */ #define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ #define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h index f0c35ce862..4fe842c3a3 100644 --- a/include/standard-headers/linux/virtio_ids.h +++ b/include/standard-headers/linux/virtio_ids.h @@ -54,7 +54,7 @@ #define VIRTIO_ID_SOUND 25 /* virtio sound */ #define VIRTIO_ID_FS 26 /* virtio filesystem */ #define VIRTIO_ID_PMEM 27 /* virtio pmem */ -#define VIRTIO_ID_BT 28 /* virtio bluetooth */ #define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */ +#define VIRTIO_ID_BT 40 /* virtio bluetooth */ #endif /* _LINUX_VIRTIO_IDS_H */ diff --git a/include/standard-headers/linux/virtio_vsock.h b/include/standard-headers/linux/virtio_vsock.h index be443211ce..3a23488e42 100644 --- a/include/standard-headers/linux/virtio_vsock.h +++ b/include/standard-headers/linux/virtio_vsock.h @@ -38,6 +38,9 @@ #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/virtio_config.h" +/* The feature bitmap for virtio vsock */ +#define VIRTIO_VSOCK_F_SEQPACKET 1 /* SOCK_SEQPACKET supported */ + struct virtio_vsock_config { uint64_t guest_cid; } QEMU_PACKED; @@ -65,6 +68,7 @@ struct virtio_vsock_hdr { enum virtio_vsock_type { VIRTIO_VSOCK_TYPE_STREAM = 1, + VIRTIO_VSOCK_TYPE_SEQPACKET = 2, }; enum virtio_vsock_op { @@ -91,4 +95,9 @@ enum virtio_vsock_shutdown { VIRTIO_VSOCK_SHUTDOWN_SEND = 2, }; +/* VIRTIO_VSOCK_OP_RW flags values */ +enum virtio_vsock_rw { + VIRTIO_VSOCK_SEQ_EOR = 1, +}; + #endif /* _LINUX_VIRTIO_VSOCK_H */ diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h index b6a0eaa32a..3d2ce9912d 100644 --- a/linux-headers/asm-arm64/kvm.h +++ b/linux-headers/asm-arm64/kvm.h @@ -184,6 +184,17 @@ struct kvm_vcpu_events { __u32 reserved[12]; }; +struct kvm_arm_copy_mte_tags { + __u64 guest_ipa; + __u64 length; + void *addr; + __u64 flags; + __u64 reserved[2]; +}; + +#define KVM_ARM_TAGS_TO_GUEST 0 +#define KVM_ARM_TAGS_FROM_GUEST 1 + /* If you need to interpret the index values, here is the key: */ #define KVM_REG_ARM_COPROC_MASK 0x000000000FFF0000 #define KVM_REG_ARM_COPROC_SHIFT 16 diff --git a/linux-headers/asm-generic/mman-common.h b/linux-headers/asm-generic/mman-common.h index f94f65d429..1567a3294c 100644 --- a/linux-headers/asm-generic/mman-common.h +++ b/linux-headers/asm-generic/mman-common.h @@ -72,6 +72,9 @@ #define MADV_COLD 20 /* deactivate these pages */ #define MADV_PAGEOUT 21 /* reclaim these pages */ +#define MADV_POPULATE_READ 22 /* populate (prefault) page tables readable */ +#define MADV_POPULATE_WRITE 23 /* populate (prefault) page tables writable */ + /* compatibility flags */ #define MAP_FILE 0 diff --git a/linux-headers/asm-generic/unistd.h b/linux-headers/asm-generic/unistd.h index 6de5a7fc06..f211961ce1 100644 --- a/linux-headers/asm-generic/unistd.h +++ b/linux-headers/asm-generic/unistd.h @@ -863,8 +863,8 @@ __SYSCALL(__NR_process_madvise, sys_process_madvise) __SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2) #define __NR_mount_setattr 442 __SYSCALL(__NR_mount_setattr, sys_mount_setattr) -#define __NR_quotactl_path 443 -__SYSCALL(__NR_quotactl_path, sys_quotactl_path) +#define __NR_quotactl_fd 443 +__SYSCALL(__NR_quotactl_fd, sys_quotactl_fd) #define __NR_landlock_create_ruleset 444 __SYSCALL(__NR_landlock_create_ruleset, sys_landlock_create_ruleset) diff --git a/linux-headers/asm-mips/mman.h b/linux-headers/asm-mips/mman.h index 57dc2ac4f8..40b210c65a 100644 --- a/linux-headers/asm-mips/mman.h +++ b/linux-headers/asm-mips/mman.h @@ -98,6 +98,9 @@ #define MADV_COLD 20 /* deactivate these pages */ #define MADV_PAGEOUT 21 /* reclaim these pages */ +#define MADV_POPULATE_READ 22 /* populate (prefault) page tables readable */ +#define MADV_POPULATE_WRITE 23 /* populate (prefault) page tables writable */ + /* compatibility flags */ #define MAP_FILE 0 diff --git a/linux-headers/asm-mips/unistd_n32.h b/linux-headers/asm-mips/unistd_n32.h index fce51fee09..09cd297698 100644 --- a/linux-headers/asm-mips/unistd_n32.h +++ b/linux-headers/asm-mips/unistd_n32.h @@ -372,6 +372,7 @@ #define __NR_process_madvise (__NR_Linux + 440) #define __NR_epoll_pwait2 (__NR_Linux + 441) #define __NR_mount_setattr (__NR_Linux + 442) +#define __NR_quotactl_fd (__NR_Linux + 443) #define __NR_landlock_create_ruleset (__NR_Linux + 444) #define __NR_landlock_add_rule (__NR_Linux + 445) #define __NR_landlock_restrict_self (__NR_Linux + 446) diff --git a/linux-headers/asm-mips/unistd_n64.h b/linux-headers/asm-mips/unistd_n64.h index 0996001802..780e0cead6 100644 --- a/linux-headers/asm-mips/unistd_n64.h +++ b/linux-headers/asm-mips/unistd_n64.h @@ -348,6 +348,7 @@ #define __NR_process_madvise (__NR_Linux + 440) #define __NR_epoll_pwait2 (__NR_Linux + 441) #define __NR_mount_setattr (__NR_Linux + 442) +#define __NR_quotactl_fd (__NR_Linux + 443) #define __NR_landlock_create_ruleset (__NR_Linux + 444) #define __NR_landlock_add_rule (__NR_Linux + 445) #define __NR_landlock_restrict_self (__NR_Linux + 446) diff --git a/linux-headers/asm-mips/unistd_o32.h b/linux-headers/asm-mips/unistd_o32.h index 954303ad69..06a2b3b55e 100644 --- a/linux-headers/asm-mips/unistd_o32.h +++ b/linux-headers/asm-mips/unistd_o32.h @@ -418,6 +418,7 @@ #define __NR_process_madvise (__NR_Linux + 440) #define __NR_epoll_pwait2 (__NR_Linux + 441) #define __NR_mount_setattr (__NR_Linux + 442) +#define __NR_quotactl_fd (__NR_Linux + 443) #define __NR_landlock_create_ruleset (__NR_Linux + 444) #define __NR_landlock_add_rule (__NR_Linux + 445) #define __NR_landlock_restrict_self (__NR_Linux + 446) diff --git a/linux-headers/asm-powerpc/unistd_32.h b/linux-headers/asm-powerpc/unistd_32.h index 9155778c19..cd5a8a41b2 100644 --- a/linux-headers/asm-powerpc/unistd_32.h +++ b/linux-headers/asm-powerpc/unistd_32.h @@ -425,6 +425,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_quotactl_fd 443 #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 diff --git a/linux-headers/asm-powerpc/unistd_64.h b/linux-headers/asm-powerpc/unistd_64.h index 3cefa88932..8458effa8d 100644 --- a/linux-headers/asm-powerpc/unistd_64.h +++ b/linux-headers/asm-powerpc/unistd_64.h @@ -397,6 +397,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_quotactl_fd 443 #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 diff --git a/linux-headers/asm-s390/unistd_32.h b/linux-headers/asm-s390/unistd_32.h index e8cd34334f..0c3cd299e4 100644 --- a/linux-headers/asm-s390/unistd_32.h +++ b/linux-headers/asm-s390/unistd_32.h @@ -415,6 +415,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_quotactl_fd 443 #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 diff --git a/linux-headers/asm-s390/unistd_64.h b/linux-headers/asm-s390/unistd_64.h index 86830e1e83..8dfc08b5e6 100644 --- a/linux-headers/asm-s390/unistd_64.h +++ b/linux-headers/asm-s390/unistd_64.h @@ -363,6 +363,7 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_quotactl_fd 443 #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h index 0662f644aa..a6c327f8ad 100644 --- a/linux-headers/asm-x86/kvm.h +++ b/linux-headers/asm-x86/kvm.h @@ -159,6 +159,19 @@ struct kvm_sregs { __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64]; }; +struct kvm_sregs2 { + /* out (KVM_GET_SREGS2) / in (KVM_SET_SREGS2) */ + struct kvm_segment cs, ds, es, fs, gs, ss; + struct kvm_segment tr, ldt; + struct kvm_dtable gdt, idt; + __u64 cr0, cr2, cr3, cr4, cr8; + __u64 efer; + __u64 apic_base; + __u64 flags; + __u64 pdptrs[4]; +}; +#define KVM_SREGS2_FLAGS_PDPTRS_VALID 1 + /* for KVM_GET_FPU and KVM_SET_FPU */ struct kvm_fpu { __u8 fpr[8][16]; diff --git a/linux-headers/asm-x86/unistd_32.h b/linux-headers/asm-x86/unistd_32.h index 8f6ac8c19f..66e96c0c68 100644 --- a/linux-headers/asm-x86/unistd_32.h +++ b/linux-headers/asm-x86/unistd_32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_UNISTD_32_H -#define _ASM_X86_UNISTD_32_H 1 +#ifndef _ASM_UNISTD_32_H +#define _ASM_UNISTD_32_H #define __NR_restart_syscall 0 #define __NR_exit 1 @@ -433,9 +433,10 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_quotactl_fd 443 #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 -#endif /* _ASM_X86_UNISTD_32_H */ +#endif /* _ASM_UNISTD_32_H */ diff --git a/linux-headers/asm-x86/unistd_64.h b/linux-headers/asm-x86/unistd_64.h index bb187a9268..b8ff6f14ee 100644 --- a/linux-headers/asm-x86/unistd_64.h +++ b/linux-headers/asm-x86/unistd_64.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_UNISTD_64_H -#define _ASM_X86_UNISTD_64_H 1 +#ifndef _ASM_UNISTD_64_H +#define _ASM_UNISTD_64_H #define __NR_read 0 #define __NR_write 1 @@ -355,9 +355,10 @@ #define __NR_process_madvise 440 #define __NR_epoll_pwait2 441 #define __NR_mount_setattr 442 +#define __NR_quotactl_fd 443 #define __NR_landlock_create_ruleset 444 #define __NR_landlock_add_rule 445 #define __NR_landlock_restrict_self 446 -#endif /* _ASM_X86_UNISTD_64_H */ +#endif /* _ASM_UNISTD_64_H */ diff --git a/linux-headers/asm-x86/unistd_x32.h b/linux-headers/asm-x86/unistd_x32.h index 4edd0103ac..06a1097c15 100644 --- a/linux-headers/asm-x86/unistd_x32.h +++ b/linux-headers/asm-x86/unistd_x32.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_UNISTD_X32_H -#define _ASM_X86_UNISTD_X32_H 1 +#ifndef _ASM_UNISTD_X32_H +#define _ASM_UNISTD_X32_H #define __NR_read (__X32_SYSCALL_BIT + 0) #define __NR_write (__X32_SYSCALL_BIT + 1) @@ -308,6 +308,7 @@ #define __NR_process_madvise (__X32_SYSCALL_BIT + 440) #define __NR_epoll_pwait2 (__X32_SYSCALL_BIT + 441) #define __NR_mount_setattr (__X32_SYSCALL_BIT + 442) +#define __NR_quotactl_fd (__X32_SYSCALL_BIT + 443) #define __NR_landlock_create_ruleset (__X32_SYSCALL_BIT + 444) #define __NR_landlock_add_rule (__X32_SYSCALL_BIT + 445) #define __NR_landlock_restrict_self (__X32_SYSCALL_BIT + 446) @@ -349,4 +350,4 @@ #define __NR_pwritev2 (__X32_SYSCALL_BIT + 547) -#endif /* _ASM_X86_UNISTD_X32_H */ +#endif /* _ASM_UNISTD_X32_H */ diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 20d6a263bb..bcaf66cc4d 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -280,6 +280,9 @@ struct kvm_xen_exit { /* Encounter unexpected vm-exit reason */ #define KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON 4 +/* Flags that describe what fields in emulation_failure hold valid data. */ +#define KVM_INTERNAL_ERROR_EMULATION_FLAG_INSTRUCTION_BYTES (1ULL << 0) + /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */ struct kvm_run { /* in */ @@ -383,6 +386,25 @@ struct kvm_run { __u32 ndata; __u64 data[16]; } internal; + /* + * KVM_INTERNAL_ERROR_EMULATION + * + * "struct emulation_failure" is an overlay of "struct internal" + * that is used for the KVM_INTERNAL_ERROR_EMULATION sub-type of + * KVM_EXIT_INTERNAL_ERROR. Note, unlike other internal error + * sub-types, this struct is ABI! It also needs to be backwards + * compatible with "struct internal". Take special care that + * "ndata" is correct, that new fields are enumerated in "flags", + * and that each flag enumerates fields that are 64-bit aligned + * and sized (so that ndata+internal.data[] is valid/accurate). + */ + struct { + __u32 suberror; + __u32 ndata; + __u64 flags; + __u8 insn_size; + __u8 insn_bytes[15]; + } emulation_failure; /* KVM_EXIT_OSI */ struct { __u64 gprs[32]; @@ -1083,6 +1105,13 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_SGX_ATTRIBUTE 196 #define KVM_CAP_VM_COPY_ENC_CONTEXT_FROM 197 #define KVM_CAP_PTP_KVM 198 +#define KVM_CAP_HYPERV_ENFORCE_CPUID 199 +#define KVM_CAP_SREGS2 200 +#define KVM_CAP_EXIT_HYPERCALL 201 +#define KVM_CAP_PPC_RPT_INVALIDATE 202 +#define KVM_CAP_BINARY_STATS_FD 203 +#define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204 +#define KVM_CAP_ARM_MTE 205 #ifdef KVM_CAP_IRQ_ROUTING @@ -1428,6 +1457,7 @@ struct kvm_s390_ucas_mapping { /* Available with KVM_CAP_PMU_EVENT_FILTER */ #define KVM_SET_PMU_EVENT_FILTER _IOW(KVMIO, 0xb2, struct kvm_pmu_event_filter) #define KVM_PPC_SVM_OFF _IO(KVMIO, 0xb3) +#define KVM_ARM_MTE_COPY_TAGS _IOR(KVMIO, 0xb4, struct kvm_arm_copy_mte_tags) /* ioctl for vm fd */ #define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device) @@ -1621,6 +1651,9 @@ struct kvm_xen_hvm_attr { #define KVM_XEN_VCPU_GET_ATTR _IOWR(KVMIO, 0xca, struct kvm_xen_vcpu_attr) #define KVM_XEN_VCPU_SET_ATTR _IOW(KVMIO, 0xcb, struct kvm_xen_vcpu_attr) +#define KVM_GET_SREGS2 _IOR(KVMIO, 0xcc, struct kvm_sregs2) +#define KVM_SET_SREGS2 _IOW(KVMIO, 0xcd, struct kvm_sregs2) + struct kvm_xen_vcpu_attr { __u16 type; __u16 pad[3]; @@ -1899,4 +1932,76 @@ struct kvm_dirty_gfn { #define KVM_BUS_LOCK_DETECTION_OFF (1 << 0) #define KVM_BUS_LOCK_DETECTION_EXIT (1 << 1) +/** + * struct kvm_stats_header - Header of per vm/vcpu binary statistics data. + * @flags: Some extra information for header, always 0 for now. + * @name_size: The size in bytes of the memory which contains statistics + * name string including trailing '\0'. The memory is allocated + * at the send of statistics descriptor. + * @num_desc: The number of statistics the vm or vcpu has. + * @id_offset: The offset of the vm/vcpu stats' id string in the file pointed + * by vm/vcpu stats fd. + * @desc_offset: The offset of the vm/vcpu stats' descriptor block in the file + * pointd by vm/vcpu stats fd. + * @data_offset: The offset of the vm/vcpu stats' data block in the file + * pointed by vm/vcpu stats fd. + * + * This is the header userspace needs to read from stats fd before any other + * readings. It is used by userspace to discover all the information about the + * vm/vcpu's binary statistics. + * Userspace reads this header from the start of the vm/vcpu's stats fd. + */ +struct kvm_stats_header { + __u32 flags; + __u32 name_size; + __u32 num_desc; + __u32 id_offset; + __u32 desc_offset; + __u32 data_offset; +}; + +#define KVM_STATS_TYPE_SHIFT 0 +#define KVM_STATS_TYPE_MASK (0xF << KVM_STATS_TYPE_SHIFT) +#define KVM_STATS_TYPE_CUMULATIVE (0x0 << KVM_STATS_TYPE_SHIFT) +#define KVM_STATS_TYPE_INSTANT (0x1 << KVM_STATS_TYPE_SHIFT) +#define KVM_STATS_TYPE_PEAK (0x2 << KVM_STATS_TYPE_SHIFT) +#define KVM_STATS_TYPE_MAX KVM_STATS_TYPE_PEAK + +#define KVM_STATS_UNIT_SHIFT 4 +#define KVM_STATS_UNIT_MASK (0xF << KVM_STATS_UNIT_SHIFT) +#define KVM_STATS_UNIT_NONE (0x0 << KVM_STATS_UNIT_SHIFT) +#define KVM_STATS_UNIT_BYTES (0x1 << KVM_STATS_UNIT_SHIFT) +#define KVM_STATS_UNIT_SECONDS (0x2 << KVM_STATS_UNIT_SHIFT) +#define KVM_STATS_UNIT_CYCLES (0x3 << KVM_STATS_UNIT_SHIFT) +#define KVM_STATS_UNIT_MAX KVM_STATS_UNIT_CYCLES + +#define KVM_STATS_BASE_SHIFT 8 +#define KVM_STATS_BASE_MASK (0xF << KVM_STATS_BASE_SHIFT) +#define KVM_STATS_BASE_POW10 (0x0 << KVM_STATS_BASE_SHIFT) +#define KVM_STATS_BASE_POW2 (0x1 << KVM_STATS_BASE_SHIFT) +#define KVM_STATS_BASE_MAX KVM_STATS_BASE_POW2 + +/** + * struct kvm_stats_desc - Descriptor of a KVM statistics. + * @flags: Annotations of the stats, like type, unit, etc. + * @exponent: Used together with @flags to determine the unit. + * @size: The number of data items for this stats. + * Every data item is of type __u64. + * @offset: The offset of the stats to the start of stat structure in + * struture kvm or kvm_vcpu. + * @unused: Unused field for future usage. Always 0 for now. + * @name: The name string for the stats. Its size is indicated by the + * &kvm_stats_header->name_size. + */ +struct kvm_stats_desc { + __u32 flags; + __s16 exponent; + __u16 size; + __u32 offset; + __u32 unused; + char name[]; +}; + +#define KVM_GET_STATS_FD _IO(KVMIO, 0xce) + #endif /* __LINUX_KVM_H */ diff --git a/linux-headers/linux/userfaultfd.h b/linux-headers/linux/userfaultfd.h index b9ac97b70f..8479af5f4c 100644 --- a/linux-headers/linux/userfaultfd.h +++ b/linux-headers/linux/userfaultfd.h @@ -31,7 +31,8 @@ UFFD_FEATURE_MISSING_SHMEM | \ UFFD_FEATURE_SIGBUS | \ UFFD_FEATURE_THREAD_ID | \ - UFFD_FEATURE_MINOR_HUGETLBFS) + UFFD_FEATURE_MINOR_HUGETLBFS | \ + UFFD_FEATURE_MINOR_SHMEM) #define UFFD_API_IOCTLS \ ((__u64)1 << _UFFDIO_REGISTER | \ (__u64)1 << _UFFDIO_UNREGISTER | \ @@ -80,8 +81,8 @@ struct uffdio_zeropage) #define UFFDIO_WRITEPROTECT _IOWR(UFFDIO, _UFFDIO_WRITEPROTECT, \ struct uffdio_writeprotect) -#define UFFDIO_CONTINUE _IOR(UFFDIO, _UFFDIO_CONTINUE, \ - struct uffdio_continue) +#define UFFDIO_CONTINUE _IOWR(UFFDIO, _UFFDIO_CONTINUE, \ + struct uffdio_continue) /* read() structure */ struct uffd_msg { @@ -185,6 +186,9 @@ struct uffdio_api { * UFFD_FEATURE_MINOR_HUGETLBFS indicates that minor faults * can be intercepted (via REGISTER_MODE_MINOR) for * hugetlbfs-backed pages. + * + * UFFD_FEATURE_MINOR_SHMEM indicates the same support as + * UFFD_FEATURE_MINOR_HUGETLBFS, but for shmem-backed pages instead. */ #define UFFD_FEATURE_PAGEFAULT_FLAG_WP (1<<0) #define UFFD_FEATURE_EVENT_FORK (1<<1) @@ -196,6 +200,7 @@ struct uffdio_api { #define UFFD_FEATURE_SIGBUS (1<<7) #define UFFD_FEATURE_THREAD_ID (1<<8) #define UFFD_FEATURE_MINOR_HUGETLBFS (1<<9) +#define UFFD_FEATURE_MINOR_SHMEM (1<<10) __u64 features; __u64 ioctls; From patchwork Fri Jul 9 05:17:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 12366755 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.8 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 E6159C07E99 for ; Fri, 9 Jul 2021 05:40: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 8055A61441 for ; Fri, 9 Jul 2021 05:40:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8055A61441 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:43634 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1jFE-0002vw-IC for qemu-devel@archiver.kernel.org; Fri, 09 Jul 2021 01:40:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35532) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuO-0002dg-60; Fri, 09 Jul 2021 01:18:40 -0400 Received: from ozlabs.org ([203.11.71.1]:41321) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1iuI-0002Ij-8Y; Fri, 09 Jul 2021 01:18:39 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4GLhHg1dL1z9tD5; Fri, 9 Jul 2021 15:17:35 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1625807855; bh=025nG769Vea+3KCrmZ338QVzQgOVZQyi2Pf0g76w1ms=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=G03PlVHwdeSH14kv6sVe6jshua/GdvAFPnyQmU2QHtbdEBtXCnsc2nBHQvBbDxLSS w9k5NPkjRUmeeQmCuZZfUU2oPMKLjsVtAY9Cineow2rMl00s2QXzUh/3cbGFys56WW xxafhGoX5uJ4Elzha2S6xbK71HAbEHz4CRwG1IDU= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 33/33] target/ppc: Support for H_RPT_INVALIDATE hcall Date: Fri, 9 Jul 2021 15:17:28 +1000 Message-Id: <20210709051728.170203-34-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210709051728.170203-1-david@gibson.dropbear.id.au> References: <20210709051728.170203-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org 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_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-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: aik@ozlabs.ru, David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, Bharata B Rao Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Bharata B Rao If KVM_CAP_RPT_INVALIDATE KVM capability is enabled, then - indicate the availability of H_RPT_INVALIDATE hcall to the guest via ibm,hypertas-functions property. - Enable the hcall Both the above are done only if the new sPAPR machine capability cap-rpt-invalidate is set. Signed-off-by: Bharata B Rao Message-Id: <20210706112440.1449562-3-bharata@linux.ibm.com> Signed-off-by: David Gibson --- hw/ppc/spapr.c | 6 ++++++ hw/ppc/spapr_caps.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/hw/ppc/spapr.h | 8 ++++++-- target/ppc/kvm.c | 12 ++++++++++++ target/ppc/kvm_ppc.h | 12 ++++++++++++ 5 files changed, 77 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 3808d47053..a007be471e 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -881,6 +881,10 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt) add_str(hypertas, "hcall-copy"); add_str(hypertas, "hcall-debug"); add_str(hypertas, "hcall-vphn"); + if (spapr_get_cap(spapr, SPAPR_CAP_RPT_INVALIDATE) == SPAPR_CAP_ON) { + add_str(hypertas, "hcall-rpt-invalidate"); + } + add_str(qemu_hypertas, "hcall-memop1"); if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { @@ -2030,6 +2034,7 @@ static const VMStateDescription vmstate_spapr = { &vmstate_spapr_cap_ccf_assist, &vmstate_spapr_cap_fwnmi, &vmstate_spapr_fwnmi, + &vmstate_spapr_cap_rpt_invalidate, NULL } }; @@ -4618,6 +4623,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON; smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_ON; smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_ON; + smc->default_caps.caps[SPAPR_CAP_RPT_INVALIDATE] = SPAPR_CAP_OFF; spapr_caps_add_properties(smc); smc->irq = &spapr_irq_dual; smc->dr_phb_enabled = true; diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c index d0c419b392..ed7c077a0d 100644 --- a/hw/ppc/spapr_caps.c +++ b/hw/ppc/spapr_caps.c @@ -582,6 +582,37 @@ static void cap_fwnmi_apply(SpaprMachineState *spapr, uint8_t val, } } +static void cap_rpt_invalidate_apply(SpaprMachineState *spapr, + uint8_t val, Error **errp) +{ + ERRP_GUARD(); + + if (!val) { + /* capability disabled by default */ + return; + } + + if (tcg_enabled()) { + error_setg(errp, "No H_RPT_INVALIDATE support in TCG"); + error_append_hint(errp, + "Try appending -machine cap-rpt-invalidate=off\n"); + } else if (kvm_enabled()) { + if (!kvmppc_has_cap_mmu_radix()) { + error_setg(errp, "H_RPT_INVALIDATE only supported on Radix"); + return; + } + + if (!kvmppc_has_cap_rpt_invalidate()) { + error_setg(errp, + "KVM implementation does not support H_RPT_INVALIDATE"); + error_append_hint(errp, + "Try appending -machine cap-rpt-invalidate=off\n"); + } else { + kvmppc_enable_h_rpt_invalidate(); + } + } +} + SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = { [SPAPR_CAP_HTM] = { .name = "htm", @@ -690,6 +721,15 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = { .type = "bool", .apply = cap_fwnmi_apply, }, + [SPAPR_CAP_RPT_INVALIDATE] = { + .name = "rpt-invalidate", + .description = "Allow H_RPT_INVALIDATE", + .index = SPAPR_CAP_RPT_INVALIDATE, + .get = spapr_cap_get_bool, + .set = spapr_cap_set_bool, + .type = "bool", + .apply = cap_rpt_invalidate_apply, + }, }; static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr, @@ -830,6 +870,7 @@ SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV); SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER); SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST); SPAPR_CAP_MIG_STATE(fwnmi, SPAPR_CAP_FWNMI); +SPAPR_CAP_MIG_STATE(rpt_invalidate, SPAPR_CAP_RPT_INVALIDATE); void spapr_caps_init(SpaprMachineState *spapr) { diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 779f707fb8..637652ad16 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -75,8 +75,10 @@ typedef enum { #define SPAPR_CAP_CCF_ASSIST 0x09 /* Implements PAPR FWNMI option */ #define SPAPR_CAP_FWNMI 0x0A +/* Support H_RPT_INVALIDATE */ +#define SPAPR_CAP_RPT_INVALIDATE 0x0B /* Num Caps */ -#define SPAPR_CAP_NUM (SPAPR_CAP_FWNMI + 1) +#define SPAPR_CAP_NUM (SPAPR_CAP_RPT_INVALIDATE + 1) /* * Capability Values @@ -547,8 +549,9 @@ struct SpaprMachineState { #define H_SCM_UNBIND_MEM 0x3F0 #define H_SCM_UNBIND_ALL 0x3FC #define H_SCM_HEALTH 0x400 +#define H_RPT_INVALIDATE 0x448 -#define MAX_HCALL_OPCODE H_SCM_HEALTH +#define MAX_HCALL_OPCODE H_RPT_INVALIDATE /* The hcalls above are standardized in PAPR and implemented by pHyp * as well. @@ -939,6 +942,7 @@ extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv; extern const VMStateDescription vmstate_spapr_cap_large_decr; extern const VMStateDescription vmstate_spapr_cap_ccf_assist; extern const VMStateDescription vmstate_spapr_cap_fwnmi; +extern const VMStateDescription vmstate_spapr_cap_rpt_invalidate; static inline uint8_t spapr_get_cap(SpaprMachineState *spapr, int cap) { diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 104a308abb..dc93b99189 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -89,6 +89,7 @@ static int cap_ppc_count_cache_flush_assist; static int cap_ppc_nested_kvm_hv; static int cap_large_decr; static int cap_fwnmi; +static int cap_rpt_invalidate; static uint32_t debug_inst_opcode; @@ -152,6 +153,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) exit(1); } + cap_rpt_invalidate = kvm_vm_check_extension(s, KVM_CAP_PPC_RPT_INVALIDATE); kvm_ppc_register_host_cpu_type(); return 0; @@ -2040,6 +2042,11 @@ void kvmppc_enable_h_page_init(void) kvmppc_enable_hcall(kvm_state, H_PAGE_INIT); } +void kvmppc_enable_h_rpt_invalidate(void) +{ + kvmppc_enable_hcall(kvm_state, H_RPT_INVALIDATE); +} + void kvmppc_set_papr(PowerPCCPU *cpu) { CPUState *cs = CPU(cpu); @@ -2551,6 +2558,11 @@ int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable) return 0; } +int kvmppc_has_cap_rpt_invalidate(void) +{ + return cap_rpt_invalidate; +} + PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void) { uint32_t host_pvr = mfpvr(); diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index 989f61ace0..ee9325bf9a 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -24,6 +24,7 @@ void kvmppc_enable_logical_ci_hcalls(void); void kvmppc_enable_set_mode_hcall(void); void kvmppc_enable_clear_ref_mod_hcalls(void); void kvmppc_enable_h_page_init(void); +void kvmppc_enable_h_rpt_invalidate(void); void kvmppc_set_papr(PowerPCCPU *cpu); int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr); void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy); @@ -71,6 +72,7 @@ bool kvmppc_has_cap_nested_kvm_hv(void); int kvmppc_set_cap_nested_kvm_hv(int enable); int kvmppc_get_cap_large_decr(void); int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable); +int kvmppc_has_cap_rpt_invalidate(void); int kvmppc_enable_hwrng(void); int kvmppc_put_books_sregs(PowerPCCPU *cpu); PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void); @@ -150,6 +152,11 @@ static inline void kvmppc_enable_h_page_init(void) { } +static inline void kvmppc_enable_h_rpt_invalidate(void) +{ + g_assert_not_reached(); +} + static inline void kvmppc_set_papr(PowerPCCPU *cpu) { } @@ -381,6 +388,11 @@ static inline int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable) return -1; } +static inline int kvmppc_has_cap_rpt_invalidate(void) +{ + return false; +} + static inline int kvmppc_enable_hwrng(void) { return -1;