From patchwork Thu Sep 26 22:24:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shawn Anastasio X-Patchwork-Id: 13813700 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D0650CDE03E for ; Thu, 26 Sep 2024 22:25:17 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.805919.1217180 (Exim 4.92) (envelope-from ) id 1stwv4-0002gd-Cg; Thu, 26 Sep 2024 22:25:06 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 805919.1217180; Thu, 26 Sep 2024 22:25:06 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1stwv4-0002fC-7V; Thu, 26 Sep 2024 22:25:06 +0000 Received: by outflank-mailman (input) for mailman id 805919; Thu, 26 Sep 2024 22:25:05 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1stwv3-0002UO-GH for xen-devel@lists.xenproject.org; Thu, 26 Sep 2024 22:25:05 +0000 Received: from raptorengineering.com (mail.raptorengineering.com [23.155.224.40]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 2b7f996d-7c56-11ef-a0ba-8be0dac302b0; Fri, 27 Sep 2024 00:25:02 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by mail.rptsys.com (Postfix) with ESMTP id C1729828533D; Thu, 26 Sep 2024 17:25:00 -0500 (CDT) Received: from mail.rptsys.com ([127.0.0.1]) by localhost (vali.starlink.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id znw22mSfNoGb; Thu, 26 Sep 2024 17:25:00 -0500 (CDT) Received: from localhost (localhost [127.0.0.1]) by mail.rptsys.com (Postfix) with ESMTP id E85528287AD2; Thu, 26 Sep 2024 17:24:59 -0500 (CDT) Received: from mail.rptsys.com ([127.0.0.1]) by localhost (vali.starlink.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id wgumsF1QtB_l; Thu, 26 Sep 2024 17:24:59 -0500 (CDT) Received: from raptor-ewks-026.rptsys.com (5.edge.rptsys.com [23.155.224.38]) by mail.rptsys.com (Postfix) with ESMTPSA id 6AF3E82875D8; Thu, 26 Sep 2024 17:24:59 -0500 (CDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 2b7f996d-7c56-11ef-a0ba-8be0dac302b0 DKIM-Filter: OpenDKIM Filter v2.10.3 mail.rptsys.com E85528287AD2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raptorengineering.com; s=B8E824E6-0BE2-11E6-931D-288C65937AAD; t=1727389499; bh=THnizrM8WgaLaQIQIbJlVxO/Ss/IgUEmhuA4iY9zqi8=; h=From:To:Date:Message-Id:MIME-Version; b=qyjb8lNeEJVOA7DrNWsd4JqmTjBTN+OojreSI5ZnhchAAwBcOnu4rG2ZMZCMQ5Uuu T4Zm7L2FnbipcTa4r01dynbuDKDPti3SZWM1x+t16JO36656wD46guRGg0D3adf13z qbJ1LQdBjYZzNnfDKhDKPT4sS3QRiQpeOtd8o2GM= X-Virus-Scanned: amavisd-new at rptsys.com From: Shawn Anastasio To: xen-devel@lists.xenproject.org Cc: tpearson@raptorengineering.com, Jan Beulich , Shawn Anastasio , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel Subject: [PATCH v5 1/3] xen/device-tree: Let DT reserve map entries overlap reserved-memory Date: Thu, 26 Sep 2024 17:24:42 -0500 Message-Id: <302647e409d91ea7ed39e568dadeedc572976c3b.1727388925.git.sanastasio@raptorengineering.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: References: MIME-Version: 1.0 Commit 53dc37829c31 ("xen/arm: Add DT reserve map regions to bootinfo.reserved_mem") changes the way reserve map regions are tracked, and as a result broke bootfdt's ability to handle device trees in which the reserve map and the `reserved-memory` node contain the same entries as each other, as is the case on PPC when booted by skiboot. Fix this behavior by moving the reserve map check to after the DT has been parsed and by explicitly allowing overlap with entries created by `reserved-memory` nodes. Fixes: 53dc37829c31 ("xen/arm: Add DT reserve map regions to bootinfo.reserved_mem") Signed-off-by: Shawn Anastasio --- xen/common/device-tree/bootfdt.c | 28 +++++++++++++++++++++++----- xen/common/device-tree/bootinfo.c | 11 +++++++++-- xen/include/xen/bootfdt.h | 3 ++- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/xen/common/device-tree/bootfdt.c b/xen/common/device-tree/bootfdt.c index 911a630e7d..2a51ee44a3 100644 --- a/xen/common/device-tree/bootfdt.c +++ b/xen/common/device-tree/bootfdt.c @@ -177,7 +177,7 @@ static int __init device_tree_get_meminfo(const void *fdt, int node, { device_tree_get_reg(&cell, address_cells, size_cells, &start, &size); if ( mem == bootinfo_get_reserved_mem() && - check_reserved_regions_overlap(start, size) ) + check_reserved_regions_overlap(start, size, NULL) ) return -EINVAL; /* Some DT may describe empty bank, ignore them */ if ( !size ) @@ -590,14 +590,36 @@ size_t __init boot_fdt_info(const void *fdt, paddr_t paddr) if ( nr_rsvd < 0 ) panic("Parsing FDT memory reserve map failed (%d)\n", nr_rsvd); + ret = device_tree_for_each_node(fdt, 0, early_scan_node, NULL); + if ( ret ) + panic("Early FDT parsing failed (%d)\n", ret); + for ( i = 0; i < nr_rsvd; i++ ) { + const struct membanks *overlap = NULL; struct membank *bank; paddr_t s, sz; if ( fdt_get_mem_rsv_paddr(device_tree_flattened, i, &s, &sz) < 0 ) continue; + if ( check_reserved_regions_overlap(s, sz, &overlap) ) + { + if ( overlap == bootinfo_get_reserved_mem() ) + { + /* + * Some valid device trees, such as those generated by OpenPOWER + * skiboot firmware, expose all reserved memory regions in the + * FDT memory reservation block (here) AND in the + * reserved-memory node which has already been parsed. Thus, any + * overlaps in the mem_reserved banks should be ignored. + */ + continue; + } + else + panic("FDT reserve map overlapped with membanks/modules\n"); + } + if ( reserved_mem->nr_banks < reserved_mem->max_banks ) { bank = &reserved_mem->bank[reserved_mem->nr_banks]; @@ -610,10 +632,6 @@ size_t __init boot_fdt_info(const void *fdt, paddr_t paddr) panic("Cannot allocate reserved memory bank\n"); } - ret = device_tree_for_each_node(fdt, 0, early_scan_node, NULL); - if ( ret ) - panic("Early FDT parsing failed (%d)\n", ret); - /* * On Arm64 setup_directmap_mappings() expects to be called with the lowest * bank in memory first. There is no requirement that the DT will provide diff --git a/xen/common/device-tree/bootinfo.c b/xen/common/device-tree/bootinfo.c index f2e6a1145b..c1752bfdc8 100644 --- a/xen/common/device-tree/bootinfo.c +++ b/xen/common/device-tree/bootinfo.c @@ -171,7 +171,8 @@ void __init fw_unreserved_regions(paddr_t s, paddr_t e, * existing reserved memory regions, otherwise false. */ bool __init check_reserved_regions_overlap(paddr_t region_start, - paddr_t region_size) + paddr_t region_size, + const struct membanks **out_overlapping_membanks) { const struct membanks *mem_banks[] = { bootinfo_get_reserved_mem(), @@ -190,8 +191,14 @@ bool __init check_reserved_regions_overlap(paddr_t region_start, * shared memory banks (when static shared memory feature is enabled) */ for ( i = 0; i < ARRAY_SIZE(mem_banks); i++ ) + { if ( meminfo_overlap_check(mem_banks[i], region_start, region_size) ) + { + if ( out_overlapping_membanks ) + *out_overlapping_membanks = mem_banks[i]; return true; + } + } /* Check if input region is overlapping with bootmodules */ if ( bootmodules_overlap_check(&bootinfo.modules, @@ -216,7 +223,7 @@ struct bootmodule __init *add_boot_module(bootmodule_kind kind, return NULL; } - if ( check_reserved_regions_overlap(start, size) ) + if ( check_reserved_regions_overlap(start, size, NULL) ) return NULL; for ( i = 0 ; i < mods->nr_mods ; i++ ) diff --git a/xen/include/xen/bootfdt.h b/xen/include/xen/bootfdt.h index 16fa05f38f..03e1d5fde8 100644 --- a/xen/include/xen/bootfdt.h +++ b/xen/include/xen/bootfdt.h @@ -158,7 +158,8 @@ struct bootinfo { extern struct bootinfo bootinfo; bool check_reserved_regions_overlap(paddr_t region_start, - paddr_t region_size); + paddr_t region_size, + const struct membanks **out_overlapping_membanks); struct bootmodule *add_boot_module(bootmodule_kind kind, paddr_t start, paddr_t size, bool domU); From patchwork Thu Sep 26 22:24:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shawn Anastasio X-Patchwork-Id: 13813701 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B7F3FCDE03F for ; Thu, 26 Sep 2024 22:25:19 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.805918.1217173 (Exim 4.92) (envelope-from ) id 1stwv4-0002X2-0K; Thu, 26 Sep 2024 22:25:06 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 805918.1217173; Thu, 26 Sep 2024 22:25:05 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1stwv3-0002WN-Po; Thu, 26 Sep 2024 22:25:05 +0000 Received: by outflank-mailman (input) for mailman id 805918; Thu, 26 Sep 2024 22:25:04 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1stwv2-0002UO-GF for xen-devel@lists.xenproject.org; Thu, 26 Sep 2024 22:25:04 +0000 Received: from raptorengineering.com (mail.raptorengineering.com [23.155.224.40]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 2be2bbc6-7c56-11ef-a0ba-8be0dac302b0; Fri, 27 Sep 2024 00:25:02 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by mail.rptsys.com (Postfix) with ESMTP id 6939282870A9; Thu, 26 Sep 2024 17:25:01 -0500 (CDT) Received: from mail.rptsys.com ([127.0.0.1]) by localhost (vali.starlink.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id sGWagBPL-OlG; Thu, 26 Sep 2024 17:25:00 -0500 (CDT) Received: from localhost (localhost [127.0.0.1]) by mail.rptsys.com (Postfix) with ESMTP id 70EA282875D8; Thu, 26 Sep 2024 17:25:00 -0500 (CDT) Received: from mail.rptsys.com ([127.0.0.1]) by localhost (vali.starlink.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id 3idvsJlGmI57; Thu, 26 Sep 2024 17:25:00 -0500 (CDT) Received: from raptor-ewks-026.rptsys.com (5.edge.rptsys.com [23.155.224.38]) by mail.rptsys.com (Postfix) with ESMTPSA id DF44C828533D; Thu, 26 Sep 2024 17:24:59 -0500 (CDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 2be2bbc6-7c56-11ef-a0ba-8be0dac302b0 DKIM-Filter: OpenDKIM Filter v2.10.3 mail.rptsys.com 70EA282875D8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raptorengineering.com; s=B8E824E6-0BE2-11E6-931D-288C65937AAD; t=1727389500; bh=uf+p5oYWeDWMIe5J8t9kSJGpxs9iSz6D7blh9z+2pl4=; h=From:To:Date:Message-Id:MIME-Version; b=theODZizRtAWRlJ2NF+GaN5HbU8wM/FAdQ63+ydPxTeeuhBIJ1qYrNvW6ojPyc0ci puCoaur0m5fez+lZZb+gc+5MdrHayJI2i0VvqYBHnYV7mNgBleVgbFxOKrd1mZUXiD YVzYDkAZENpgnRu3xWZu0jHLAg3D0HHWht44VkuY= X-Virus-Scanned: amavisd-new at rptsys.com From: Shawn Anastasio To: xen-devel@lists.xenproject.org Cc: tpearson@raptorengineering.com, Jan Beulich , Shawn Anastasio , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Julien Grall Subject: [PATCH v5 2/3] xen/ppc: Enable bootfdt and boot allocator Date: Thu, 26 Sep 2024 17:24:43 -0500 Message-Id: <423472f8bcc4b6800e2ed8d6065b2bb0fc1f8ebc.1727388925.git.sanastasio@raptorengineering.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: References: MIME-Version: 1.0 Enable usage of bootfdt for populating the boot info struct from the firmware-provided device tree. Also enable the Xen boot page allocator. Additionally, modify bootfdt.c's boot_fdt_info() to tolerate the scenario in which the FDT overlaps a reserved memory region, as is the case on PPC when booted directly from skiboot. Since this means that Xen can now boot without a BOOTMOD_FDT present in bootinfo, clarify this fact in a comment above BOOTMOD_FDT's definition. Signed-off-by: Shawn Anastasio Acked-by: Julien Grall --- Changes in v5: - Drop setup.c's unnecessary `boot_fdt` variable per Julien's suggestion xen/arch/ppc/setup.c | 20 +++++++++++++++++++- xen/common/device-tree/bootfdt.c | 11 +++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) -- 2.30.2 diff --git a/xen/arch/ppc/setup.c b/xen/arch/ppc/setup.c index 5fb5ab64e3..17bc1aed34 100644 --- a/xen/arch/ppc/setup.c +++ b/xen/arch/ppc/setup.c @@ -1,4 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include +#include #include #include #include @@ -9,6 +11,7 @@ #include #include #include +#include /* Xen stack for bringing up the first CPU. */ unsigned char __initdata cpu0_boot_stack[STACK_SIZE] __aligned(STACK_SIZE); @@ -26,6 +29,8 @@ void __init noreturn start_xen(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { + const struct bootmodule *xen_bootmodule; + if ( r5 ) { /* Unsupported OpenFirmware boot protocol */ @@ -34,11 +39,24 @@ void __init noreturn start_xen(unsigned long r3, unsigned long r4, else { /* kexec boot protocol */ - boot_opal_init((void *)r3); + device_tree_flattened = (void *)r3; + boot_opal_init(device_tree_flattened); } setup_exceptions(); + boot_fdt_info(device_tree_flattened, r3); + + /* + * Xen relocates itself at the ppc64 entrypoint, so we need to manually mark + * the kernel module. + */ + xen_bootmodule = add_boot_module(BOOTMOD_XEN, __pa(_start), + PAGE_ALIGN(__pa(_end)), false); + BUG_ON(!xen_bootmodule); + + populate_boot_allocator(); + setup_initial_pagetables(); init_constructors(); diff --git a/xen/common/device-tree/bootfdt.c b/xen/common/device-tree/bootfdt.c index 2a51ee44a3..5facd683b8 100644 --- a/xen/common/device-tree/bootfdt.c +++ b/xen/common/device-tree/bootfdt.c @@ -584,8 +584,6 @@ size_t __init boot_fdt_info(const void *fdt, paddr_t paddr) if ( ret < 0 ) panic("No valid device tree\n"); - add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), false); - nr_rsvd = fdt_num_mem_rsv(fdt); if ( nr_rsvd < 0 ) panic("Parsing FDT memory reserve map failed (%d)\n", nr_rsvd); @@ -632,6 +630,15 @@ size_t __init boot_fdt_info(const void *fdt, paddr_t paddr) panic("Cannot allocate reserved memory bank\n"); } + /* + * Add module for the FDT itself after the device tree has been parsed. This + * is required on ppc64le where the device tree passed to Xen may have been + * allocated by skiboot, in which case it will exist within a reserved + * region and this call will fail. This is fine, however, since either way + * the allocator will know not to step on the device tree. + */ + (void)add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), false); + /* * On Arm64 setup_directmap_mappings() expects to be called with the lowest * bank in memory first. There is no requirement that the DT will provide From patchwork Thu Sep 26 22:24:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shawn Anastasio X-Patchwork-Id: 13813703 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9D22DCCFA17 for ; Thu, 26 Sep 2024 22:25:20 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.805920.1217197 (Exim 4.92) (envelope-from ) id 1stwv5-0003By-J2; Thu, 26 Sep 2024 22:25:07 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 805920.1217197; Thu, 26 Sep 2024 22:25:07 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1stwv5-0003Br-GE; Thu, 26 Sep 2024 22:25:07 +0000 Received: by outflank-mailman (input) for mailman id 805920; Thu, 26 Sep 2024 22:25:06 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1stwv3-0002V3-W8 for xen-devel@lists.xenproject.org; Thu, 26 Sep 2024 22:25:05 +0000 Received: from raptorengineering.com (mail.raptorengineering.com [23.155.224.40]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 2c8c2c18-7c56-11ef-99a2-01e77a169b0f; Fri, 27 Sep 2024 00:25:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by mail.rptsys.com (Postfix) with ESMTP id 9A15582875D8; Thu, 26 Sep 2024 17:25:02 -0500 (CDT) Received: from mail.rptsys.com ([127.0.0.1]) by localhost (vali.starlink.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id QOKNOPx6MOA3; Thu, 26 Sep 2024 17:25:00 -0500 (CDT) Received: from localhost (localhost [127.0.0.1]) by mail.rptsys.com (Postfix) with ESMTP id C7CD68287AF6; Thu, 26 Sep 2024 17:25:00 -0500 (CDT) Received: from mail.rptsys.com ([127.0.0.1]) by localhost (vali.starlink.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id b1KiKTt7BInO; Thu, 26 Sep 2024 17:25:00 -0500 (CDT) Received: from raptor-ewks-026.rptsys.com (5.edge.rptsys.com [23.155.224.38]) by mail.rptsys.com (Postfix) with ESMTPSA id 6E2A282870A9; Thu, 26 Sep 2024 17:25:00 -0500 (CDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 2c8c2c18-7c56-11ef-99a2-01e77a169b0f DKIM-Filter: OpenDKIM Filter v2.10.3 mail.rptsys.com C7CD68287AF6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raptorengineering.com; s=B8E824E6-0BE2-11E6-931D-288C65937AAD; t=1727389500; bh=YYxx5HUZxjPW1IsF8Z0FYs/3hWd+njQij1zrklGXAr0=; h=From:To:Date:Message-Id:MIME-Version; b=TUZvxOEv2KZWyOL4nnxd35TUBKQlklUaLNvhZLoeFxQs5Fp74q5+aCr38tGzKoUWu dQUxkmZsoryNus49bmMTihf/m/EF86SWiremd6WSCGO9URvsG0R5nlacWNDIRHKw/c Y43b74pc1kD4XTWL86Hz0Sovb9L5uiWrkUpvr/zk= X-Virus-Scanned: amavisd-new at rptsys.com From: Shawn Anastasio To: xen-devel@lists.xenproject.org Cc: tpearson@raptorengineering.com, Jan Beulich , Shawn Anastasio Subject: [PATCH v5 3/3] xen/ppc: mm-radix: Allocate all paging structures at runtime Date: Thu, 26 Sep 2024 17:24:44 -0500 Message-Id: X-Mailer: git-send-email 2.30.2 In-Reply-To: References: MIME-Version: 1.0 In the initial mm-radix implementation, the in-memory partition and process tables required to configure the MMU, as well as the page tables themselves were all allocated statically since the boot allocator was not yet available. Now that it is, allocate these structures at runtime and bump the size of the Process Table to its maximum supported value (on POWER9). Signed-off-by: Shawn Anastasio Acked-by: Jan Beulich --- Changes in v5: - Add more clarification comments to min/max mfn variable decls. Changes in v4: - use mfn_add in initial_page_alloc() - zero pages returned by initial_page_alloc() xen/arch/ppc/mm-radix.c | 238 ++++++++++++++++++++++------------------ 1 file changed, 130 insertions(+), 108 deletions(-) -- 2.30.2 diff --git a/xen/arch/ppc/mm-radix.c b/xen/arch/ppc/mm-radix.c index 24232f3907..e3bf41675b 100644 --- a/xen/arch/ppc/mm-radix.c +++ b/xen/arch/ppc/mm-radix.c @@ -22,69 +22,112 @@ void enable_mmu(void); #define radix_dprintk(...) #endif -#define INITIAL_LVL1_PD_COUNT 1 -#define INITIAL_LVL2_LVL3_PD_COUNT 2 -#define INITIAL_LVL4_PT_COUNT 256 - -static size_t __initdata initial_lvl1_pd_pool_used; -static struct lvl1_pd initial_lvl1_pd_pool[INITIAL_LVL1_PD_COUNT]; - -static size_t __initdata initial_lvl2_lvl3_pd_pool_used; -static struct lvl2_pd initial_lvl2_lvl3_pd_pool[INITIAL_LVL2_LVL3_PD_COUNT]; - -static size_t __initdata initial_lvl4_pt_pool_used; -static struct lvl4_pt initial_lvl4_pt_pool[INITIAL_LVL4_PT_COUNT]; - -/* Only reserve minimum Partition and Process tables */ #define PATB_SIZE_LOG2 16 /* Only supported partition table size on POWER9 */ #define PATB_SIZE (1UL << PATB_SIZE_LOG2) -#define PRTB_SIZE_LOG2 12 +#define PRTB_SIZE_LOG2 24 /* Maximum process table size on POWER9 */ #define PRTB_SIZE (1UL << PRTB_SIZE_LOG2) -static struct patb_entry - __aligned(PATB_SIZE) initial_patb[PATB_SIZE / sizeof(struct patb_entry)]; +static struct patb_entry *initial_patb; +static struct prtb_entry *initial_prtb; -static struct prtb_entry - __aligned(PRTB_SIZE) initial_prtb[PRTB_SIZE / sizeof(struct prtb_entry)]; +/* + * The highest and lowest mfns returned by initial_page_alloc. In order to + * bootstrap the xen's initial page tables, the mfns allocated to store the + * paging structurs needs to be tracked so that they can be included in the + * mapping. This is most simply accomplished by keeping track of the minimum + * and maximum mfn numbers so that the whole range from min->max can be mapped. + */ +static mfn_t __initdata min_alloc_mfn = {-1}; +static mfn_t __initdata max_alloc_mfn = {0}; -static __init struct lvl1_pd *lvl1_pd_pool_alloc(void) +/* + * A thin wrapper for alloc_boot_pages that keeps track of the maximum and + * minimum mfns that have been allocated. This information is used by + * setup_initial_mapping to include the allocated pages in the initial + * page mapping. + * + * Additionally, allocated pages are zeroed before return. + */ +static mfn_t __init initial_page_alloc(unsigned long nr_pfns, + unsigned long pfn_align) { - if ( initial_lvl1_pd_pool_used >= INITIAL_LVL1_PD_COUNT ) - { - early_printk("Ran out of space for LVL1 PD!\n"); - die(); - } + mfn_t mfn_first, mfn_last; - return &initial_lvl1_pd_pool[initial_lvl1_pd_pool_used++]; -} + mfn_first = alloc_boot_pages(nr_pfns, pfn_align); + mfn_last = mfn_add(mfn_first, nr_pfns - 1); -static __init struct lvl2_pd *lvl2_pd_pool_alloc(void) -{ - if ( initial_lvl2_lvl3_pd_pool_used >= INITIAL_LVL2_LVL3_PD_COUNT ) - { - early_printk("Ran out of space for LVL2/3 PD!\n"); - die(); - } + min_alloc_mfn = _mfn(min(mfn_x(min_alloc_mfn), mfn_x(mfn_first))); + max_alloc_mfn = _mfn(max(mfn_x(max_alloc_mfn), mfn_x(mfn_last))); + + memset(__va(mfn_to_maddr(mfn_first)), 0, nr_pfns << PAGE_SHIFT); - return &initial_lvl2_lvl3_pd_pool[initial_lvl2_lvl3_pd_pool_used++]; + return mfn_first; } -static __init struct lvl3_pd *lvl3_pd_pool_alloc(void) +static __init void *initial_pd_pt_alloc(void) { - BUILD_BUG_ON(sizeof(struct lvl3_pd) != sizeof(struct lvl2_pd)); + BUILD_BUG_ON(sizeof(struct lvl1_pd) > PAGE_SIZE); + BUILD_BUG_ON(sizeof(struct lvl2_pd) > PAGE_SIZE); + BUILD_BUG_ON(sizeof(struct lvl3_pd) > PAGE_SIZE); + BUILD_BUG_ON(sizeof(struct lvl4_pt) > PAGE_SIZE); - return (struct lvl3_pd *) lvl2_pd_pool_alloc(); + return __va(mfn_to_maddr(initial_page_alloc(1, 1))); } -static __init struct lvl4_pt *lvl4_pt_pool_alloc(void) +static void map_page_initial(struct lvl1_pd *lvl1, vaddr_t virt, paddr_t phys, + unsigned long flags) { - if ( initial_lvl4_pt_pool_used >= INITIAL_LVL4_PT_COUNT ) + struct lvl2_pd *lvl2; + struct lvl3_pd *lvl3; + struct lvl4_pt *lvl4; + pde_t *pde; + pte_t *pte; + + /* Allocate LVL 2 PD if necessary */ + pde = pt_entry(lvl1, virt); + if ( !pde_is_valid(*pde) ) { - early_printk("Ran out of space for LVL4 PT!\n"); - die(); + lvl2 = initial_pd_pt_alloc(); + *pde = paddr_to_pde(__pa(lvl2), PDE_VALID, + XEN_PT_ENTRIES_LOG2_LVL_2); } + else + lvl2 = __va(pde_to_paddr(*pde)); - return &initial_lvl4_pt_pool[initial_lvl4_pt_pool_used++]; + /* Allocate LVL 3 PD if necessary */ + pde = pt_entry(lvl2, virt); + if ( !pde_is_valid(*pde) ) + { + lvl3 = initial_pd_pt_alloc(); + *pde = paddr_to_pde(__pa(lvl3), PDE_VALID, + XEN_PT_ENTRIES_LOG2_LVL_3); + } + else + lvl3 = __va(pde_to_paddr(*pde)); + + /* Allocate LVL 4 PT if necessary */ + pde = pt_entry(lvl3, virt); + if ( !pde_is_valid(*pde) ) + { + lvl4 = initial_pd_pt_alloc(); + *pde = paddr_to_pde(__pa(lvl4), PDE_VALID, + XEN_PT_ENTRIES_LOG2_LVL_4); + } + else + lvl4 = __va(pde_to_paddr(*pde)); + + /* Finally, create PTE in LVL 4 PT */ + pte = pt_entry(lvl4, virt); + if ( !pte_is_valid(*pte) ) + { + radix_dprintk("%016lx being mapped to %016lx\n", phys, virt); + *pte = paddr_to_pte(phys, flags); + } + else + { + early_printk("BUG: Tried to create PTE for already-mapped page!"); + die(); + } } static void __init setup_initial_mapping(struct lvl1_pd *lvl1, @@ -93,6 +136,7 @@ static void __init setup_initial_mapping(struct lvl1_pd *lvl1, paddr_t phys_base) { uint64_t page_addr; + mfn_t previous_max_alloc_mfn; if ( map_start & ~PAGE_MASK ) { @@ -106,81 +150,47 @@ static void __init setup_initial_mapping(struct lvl1_pd *lvl1, die(); } + /* Identity map Xen itself */ for ( page_addr = map_start; page_addr < map_end; page_addr += PAGE_SIZE ) { - struct lvl2_pd *lvl2; - struct lvl3_pd *lvl3; - struct lvl4_pt *lvl4; - pde_t *pde; - pte_t *pte; - - /* Allocate LVL 2 PD if necessary */ - pde = pt_entry(lvl1, page_addr); - if ( !pde_is_valid(*pde) ) - { - lvl2 = lvl2_pd_pool_alloc(); - *pde = paddr_to_pde(__pa(lvl2), PDE_VALID, - XEN_PT_ENTRIES_LOG2_LVL_2); - } - else - lvl2 = __va(pde_to_paddr(*pde)); - - /* Allocate LVL 3 PD if necessary */ - pde = pt_entry(lvl2, page_addr); - if ( !pde_is_valid(*pde) ) - { - lvl3 = lvl3_pd_pool_alloc(); - *pde = paddr_to_pde(__pa(lvl3), PDE_VALID, - XEN_PT_ENTRIES_LOG2_LVL_3); - } - else - lvl3 = __va(pde_to_paddr(*pde)); + unsigned long flags; - /* Allocate LVL 4 PT if necessary */ - pde = pt_entry(lvl3, page_addr); - if ( !pde_is_valid(*pde) ) + if ( is_kernel_text(page_addr) || is_kernel_inittext(page_addr) ) { - lvl4 = lvl4_pt_pool_alloc(); - *pde = paddr_to_pde(__pa(lvl4), PDE_VALID, - XEN_PT_ENTRIES_LOG2_LVL_4); + radix_dprintk("%016lx being marked as TEXT (RX)\n", page_addr); + flags = PTE_XEN_RX; } - else - lvl4 = __va(pde_to_paddr(*pde)); - - /* Finally, create PTE in LVL 4 PT */ - pte = pt_entry(lvl4, page_addr); - if ( !pte_is_valid(*pte) ) + else if ( is_kernel_rodata(page_addr) ) { - unsigned long paddr = (page_addr - map_start) + phys_base; - unsigned long flags; - - radix_dprintk("%016lx being mapped to %016lx\n", paddr, page_addr); - if ( is_kernel_text(page_addr) || is_kernel_inittext(page_addr) ) - { - radix_dprintk("%016lx being marked as TEXT (RX)\n", page_addr); - flags = PTE_XEN_RX; - } - else if ( is_kernel_rodata(page_addr) ) - { - radix_dprintk("%016lx being marked as RODATA (RO)\n", page_addr); - flags = PTE_XEN_RO; - } - else - { - radix_dprintk("%016lx being marked as DEFAULT (RW)\n", page_addr); - flags = PTE_XEN_RW; - } - - *pte = paddr_to_pte(paddr, flags); - radix_dprintk("%016lx is the result of PTE map\n", - paddr_to_pte(paddr, flags).pte); + radix_dprintk("%016lx being marked as RODATA (RO)\n", page_addr); + flags = PTE_XEN_RO; } else { - early_printk("BUG: Tried to create PTE for already-mapped page!"); - die(); + radix_dprintk("%016lx being marked as DEFAULT (RW)\n", page_addr); + flags = PTE_XEN_RW; } + + map_page_initial(lvl1, page_addr, (page_addr - map_start) + phys_base, flags); } + + previous_max_alloc_mfn = max_alloc_mfn; + + /* + * Identity map all pages we've allocated for paging structures. This act + * itself will allocate more pages, so continue until we've mapped from + * `max_alloc_mfn` down to `min_alloc_mfn`. This assumes that the heap grows + * downwards, which matches the behavior of alloc_boot_pages. + */ + for ( page_addr = (vaddr_t)__va(mfn_to_maddr(max_alloc_mfn)); + mfn_to_maddr(min_alloc_mfn) <= __pa(page_addr); + page_addr -= PAGE_SIZE) + { + map_page_initial(lvl1, page_addr, __pa(page_addr), PTE_XEN_RW); + } + + if ( mfn_x(previous_max_alloc_mfn) != mfn_x(max_alloc_mfn) ) + panic("Early page heap unexpectedly grew upwards\n"); } static void __init setup_partition_table(struct lvl1_pd *root) @@ -209,9 +219,21 @@ static void __init setup_process_table(struct lvl1_pd *root) void __init setup_initial_pagetables(void) { - struct lvl1_pd *root = lvl1_pd_pool_alloc(); + struct lvl1_pd *root; unsigned long lpcr; + mfn_t patb_mfn, prtb_mfn; + + /* Allocate mfns for in-memory tables using the boot allocator */ + prtb_mfn = initial_page_alloc(PRTB_SIZE / PAGE_SIZE, + 1 << (PRTB_SIZE_LOG2 - PAGE_SHIFT)); + patb_mfn = initial_page_alloc(PATB_SIZE / PAGE_SIZE, + 1 << (PATB_SIZE_LOG2 - PAGE_SHIFT)); + + initial_patb = __va(mfn_to_maddr(patb_mfn)); + initial_prtb = __va(mfn_to_maddr(prtb_mfn)); + /* Allocate and create page tables */ + root = initial_pd_pt_alloc(); setup_initial_mapping(root, (vaddr_t)_start, (vaddr_t)_end, __pa(_start)); /* Enable Radix mode in LPCR */