From nobody Fri Dec 19 07:21:28 2025 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 703F61B81AB; Fri, 30 Aug 2024 16:29:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725035397; cv=none; b=CIxjX95slH2G2P2GLVRFlpVhReGW0k93xRqb2cEJr9RtHHrsQ/pNysjeml0h6KKBGQUfboWqq/c+5wzXyWIHQv4Cs8LrM3NRxfilqHeBH0KctaZWh8onKixuaX30Xv8tWVJ6Ve0CR0f15Sh+ZZytnJf/iPbdHckvfBtSJbTjQ38= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725035397; c=relaxed/simple; bh=9tb+QvXsbxvTlr6wwJYHnT1Gf+BARq5gDNcCrjF/3ZI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Qwo46FRNm/L4hMkTJE8/hJ4loEEiQMd8tZ9QDxaQZTDLxpJKMLpxJAXBlLDOk3Tjg0xg0PERehXwMwJznGP/KuKn6eS7AwVWH/og8uT53nHOqHhtDhOYST07MEXlVo0XaPhPehVmPfIcxwqedkOCVeYGws6tEL1YNk0yEwMUlBQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=UHw3IiN+; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="UHw3IiN+" Received: from pps.filterd (m0279867.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 47UFCLGo018470; Fri, 30 Aug 2024 16:29:35 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= gq0e0C2ozqdCwoEf5P7f+RQW8madfJm9dl3WCLwcoYA=; b=UHw3IiN+kdxYflL/ 1dlxUu0ai0UUuvJKuXE6uPxA0l/9Emg+xMVTI5tUjLUgOsrt5Ts4li8yj4N9QCpa StUmkOoRftSL1CjjPzi822V80q4EjhK79vnaWKtyttqzd32+pTCXHFFy/gFk2zsy vkEDcUyGwi+smjOX2wDH4UQTPSPiNNlym1O1sz80JnXZe8wkK986dMG9QJ1w/Boj jNt07oDBW+f2+YcnNhvnNPNbm86etR8LVQc1hz85xWeeNXLM78/aHcTA8IEXTsoq 3BJNcOklRlg18HrqizOino3Qh5VCzU+M8rLCTiOMRUbkuUzgKX53zGy32DQHAo6X r9sycA== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 419putskdr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 30 Aug 2024 16:29:34 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 47UGTXYB011671 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 30 Aug 2024 16:29:33 GMT Received: from hu-obabatun-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Fri, 30 Aug 2024 09:29:30 -0700 From: Oreoluwa Babatunde To: CC: , , , , , , , , , , , , , Subject: [PATCH v8 1/2] of: reserved_mem: Restruture how the reserved memory regions are processed Date: Fri, 30 Aug 2024 09:28:56 -0700 Message-ID: <20240830162857.2821502-2-quic_obabatun@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240830162857.2821502-1-quic_obabatun@quicinc.com> References: <20240830162857.2821502-1-quic_obabatun@quicinc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: aztyn3rGBVVerS9qlJA5FfE2KnafPMOy X-Proofpoint-ORIG-GUID: aztyn3rGBVVerS9qlJA5FfE2KnafPMOy X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-08-30_10,2024-08-30_01,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 phishscore=0 adultscore=0 priorityscore=1501 impostorscore=0 malwarescore=0 suspectscore=0 spamscore=0 bulkscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2407110000 definitions=main-2408300125 Content-Type: text/plain; charset="utf-8" Reserved memory regions defined in the devicetree can be broken up into two groups: i) Statically-placed reserved memory regions i.e. regions defined with a static start address and size using the "reg" property. ii) Dynamically-placed reserved memory regions. i.e. regions defined by specifying an address range where they can be placed in memory using the "alloc_ranges" and "size" properties. These regions are processed and set aside at boot time. This is done in two stages as seen below: Stage 1: At this stage, fdt_scan_reserved_mem() scans through the child nodes of the reserved_memory node using the flattened devicetree and does the following: 1) If the node represents a statically-placed reserved memory region, i.e. if it is defined using the "reg" property: - Call memblock_reserve() or memblock_mark_nomap() as needed. - Add the information for that region into the reserved_mem array using fdt_reserved_mem_save_node(). i.e. fdt_reserved_mem_save_node(node, name, base, size). 2) If the node represents a dynamically-placed reserved memory region, i.e. if it is defined using "alloc-ranges" and "size" properties: - Add the information for that region to the reserved_mem array with the starting address and size set to 0. i.e. fdt_reserved_mem_save_node(node, name, 0, 0). Note: This region is saved to the array with a starting address of 0 because a starting address is not yet allocated for it. Stage 2: After iterating through all the reserved memory nodes and storing their relevant information in the reserved_mem array,fdt_init_reserved_mem() is called and does the following: 1) For statically-placed reserved memory regions: - Call the region specific init function using __reserved_mem_init_node(). 2) For dynamically-placed reserved memory regions: - Call __reserved_mem_alloc_size() which is used to allocate memory for each of these regions, and mark them as nomap if they have the nomap property specified in the DT. - Call the region specific init function. The current size of the resvered_mem array is 64 as is defined by MAX_RESERVED_REGIONS. This means that there is a limitation of 64 for how many reserved memory regions can be specified on a system. As systems continue to grow more and more complex, the number of reserved memory regions needed are also growing and are starting to hit this 64 count limit, hence the need to make the reserved_mem array dynamically sized (i.e. dynamically allocating memory for the reserved_mem array using membock_alloc_*). On architectures such as arm64, memory allocated using memblock is writable only after the page tables have been setup. This means that if the reserved_mem array is going to be dynamically allocated, it needs to happen after the page tables have been setup, not before. Since the reserved memory regions are currently being processed and added to the array before the page tables are setup, there is a need to change the order in which some of the processing is done to allow for the reserved_mem array to be dynamically sized. It is possible to process the statically-placed reserved memory regions without needing to store them in the reserved_mem array until after the page tables have been setup because all the information stored in the array is readily available in the devicetree and can be referenced at any time. Dynamically-placed reserved memory regions on the other hand get assigned a start address only at runtime, and hence need a place to be stored once they are allocated since there is no other referrence to the start address for these regions. Hence this patch changes the processing order of the reserved memory regions in the following ways: Step 1: fdt_scan_reserved_mem() scans through the child nodes of the reserved_memory node using the flattened devicetree and does the following: 1) If the node represents a statically-placed reserved memory region, i.e. if it is defined using the "reg" property: - Call memblock_reserve() or memblock_mark_nomap() as needed. - Call the region specific initialization function for the region using fdt_init_reserved_mem_node(). 2) If the node represents a dynamically-placed reserved memory region, i.e. if it is defined using "alloc-ranges" and "size" properties: - Call __reserved_mem_alloc_size() which will: i) Allocate memory for the reserved region and call memblock_mark_nomap() as needed. ii) Call the region specific initialization function using fdt_init_reserved_mem_node(). iii) Save the region information in the reserved_mem array using fdt_reserved_mem_save_node(). Step 2: 1) This stage of the reserved memory processing is now only used to add the statically-placed reserved memory regions into the reserved_mem array using fdt_scan_reserved_mem_reg_nodes(). 2) This step is also moved to be after the page tables have been setup. Moving this will allow us to replace the reserved_mem array with a dynamically sized array before storing the rest of these regions. Signed-off-by: Oreoluwa Babatunde Tested-by: Klara Modin Tested-by: Ninad Naik # sa8775p-ride --- drivers/of/fdt.c | 5 +- drivers/of/of_private.h | 3 +- drivers/of/of_reserved_mem.c | 175 ++++++++++++++++++++++++++--------- 3 files changed, 134 insertions(+), 49 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 68103ad230ee..276d189e808b 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -511,8 +511,6 @@ void __init early_init_fdt_scan_reserved_mem(void) break; memblock_reserve(base, size); } - - fdt_init_reserved_mem(); } =20 /** @@ -1212,6 +1210,9 @@ void __init unflatten_device_tree(void) { void *fdt =3D initial_boot_params; =20 + /* Save the statically-placed regions in the reserved_mem array */ + fdt_scan_reserved_mem_reg_nodes(); + /* Don't use the bootloader provided DTB if ACPI is enabled */ if (!acpi_disabled) fdt =3D NULL; diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index 04aa2a91f851..29525c0b9939 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -9,6 +9,7 @@ */ =20 #define FDT_ALIGN_SIZE 8 +#define MAX_RESERVED_REGIONS 64 =20 /** * struct alias_prop - Alias property in 'aliases' node @@ -180,7 +181,7 @@ static inline struct device_node *__of_get_dma_parent(c= onst struct device_node * #endif =20 int fdt_scan_reserved_mem(void); -void fdt_init_reserved_mem(void); +void __init fdt_scan_reserved_mem_reg_nodes(void); =20 bool of_fdt_device_is_available(const void *blob, unsigned long node); =20 diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 46e1c3fbc769..a4487ee6c5ca 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -27,7 +27,6 @@ =20 #include "of_private.h" =20 -#define MAX_RESERVED_REGIONS 64 static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; static int reserved_mem_count; =20 @@ -96,6 +95,8 @@ static int __init early_init_dt_reserve_memory(phys_addr_= t base, return memblock_reserve(base, size); } =20 +static void __init fdt_init_reserved_mem_node(unsigned long node, const ch= ar *uname, + phys_addr_t base, phys_addr_t size); /* * __reserved_mem_reserve_reg() - reserve all memory described in 'reg' pr= operty */ @@ -135,7 +136,8 @@ static int __init __reserved_mem_reserve_reg(unsigned l= ong node, =20 len -=3D t_len; if (first) { - fdt_reserved_mem_save_node(node, uname, base, size); + /* Call region specific initialization function */ + fdt_init_reserved_mem_node(node, uname, base, size); first =3D 0; } } @@ -165,12 +167,77 @@ static int __init __reserved_mem_check_root(unsigned = long node) return 0; } =20 +static void __init __rmem_check_for_overlap(void); + +/** + * fdt_scan_reserved_mem_reg_nodes() - Store info for the "reg" defined + * reserved memory regions. + * + * This function is used to scan through the DT and store the + * information for the reserved memory regions that are defined using + * the "reg" property. The region node number, name, base address, and + * size are all stored in the reserved_mem array by calling the + * fdt_reserved_mem_save_node() function. + */ +void __init fdt_scan_reserved_mem_reg_nodes(void) +{ + int t_len =3D (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); + const void *fdt =3D initial_boot_params; + phys_addr_t base, size; + const __be32 *prop; + int node, child; + int len; + + if (!fdt) + return; + + node =3D fdt_path_offset(fdt, "/reserved-memory"); + if (node < 0) { + pr_info("Reserved memory: No reserved-memory node in the DT\n"); + return; + } + + if (__reserved_mem_check_root(node)) { + pr_err("Reserved memory: unsupported node format, ignoring\n"); + return; + } + + fdt_for_each_subnode(child, fdt, node) { + const char *uname; + + prop =3D of_get_flat_dt_prop(child, "reg", &len); + if (!prop) + continue; + if (!of_fdt_device_is_available(fdt, child)) + continue; + + uname =3D fdt_get_name(fdt, child, NULL); + if (len && len % t_len !=3D 0) { + pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n= ", + uname); + continue; + } + base =3D dt_mem_next_cell(dt_root_addr_cells, &prop); + size =3D dt_mem_next_cell(dt_root_size_cells, &prop); + + if (size) + fdt_reserved_mem_save_node(child, uname, base, size); + } + + /* check for overlapping reserved regions */ + __rmem_check_for_overlap(); +} + +static int __init __reserved_mem_alloc_size(unsigned long node, const char= *uname); + /* * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory */ int __init fdt_scan_reserved_mem(void) { int node, child; + int dynamic_nodes_cnt =3D 0; + int dynamic_nodes[MAX_RESERVED_REGIONS]; const void *fdt =3D initial_boot_params; =20 node =3D fdt_path_offset(fdt, "/reserved-memory"); @@ -192,8 +259,24 @@ int __init fdt_scan_reserved_mem(void) uname =3D fdt_get_name(fdt, child, NULL); =20 err =3D __reserved_mem_reserve_reg(child, uname); - if (err =3D=3D -ENOENT && of_get_flat_dt_prop(child, "size", NULL)) - fdt_reserved_mem_save_node(child, uname, 0, 0); + /* + * Save the nodes for the dynamically-placed regions + * into an array which will be used for allocation right + * after all the statically-placed regions are reserved + * or marked as no-map. This is done to avoid dynamically + * allocating from one of the statically-placed regions. + */ + if (err =3D=3D -ENOENT && of_get_flat_dt_prop(child, "size", NULL)) { + dynamic_nodes[dynamic_nodes_cnt] =3D child; + dynamic_nodes_cnt++; + } + } + for (int i =3D 0; i < dynamic_nodes_cnt; i++) { + const char *uname; + + child =3D dynamic_nodes[i]; + uname =3D fdt_get_name(fdt, child, NULL); + __reserved_mem_alloc_size(child, uname); } return 0; } @@ -253,8 +336,7 @@ static int __init __reserved_mem_alloc_in_range(phys_ad= dr_t size, * __reserved_mem_alloc_size() - allocate reserved memory described by * 'size', 'alignment' and 'alloc-ranges' properties. */ -static int __init __reserved_mem_alloc_size(unsigned long node, - const char *uname, phys_addr_t *res_base, phys_addr_t *res_size) +static int __init __reserved_mem_alloc_size(unsigned long node, const char= *uname) { int t_len =3D (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); phys_addr_t start =3D 0, end =3D 0; @@ -334,9 +416,11 @@ static int __init __reserved_mem_alloc_size(unsigned l= ong node, return -ENOMEM; } =20 - *res_base =3D base; - *res_size =3D size; + /* Call region specific initialization function */ + fdt_init_reserved_mem_node(node, uname, base, size); =20 + /* Save region in the reserved_mem array */ + fdt_reserved_mem_save_node(node, uname, base, size); return 0; } =20 @@ -425,48 +509,47 @@ static void __init __rmem_check_for_overlap(void) } =20 /** - * fdt_init_reserved_mem() - allocate and init all saved reserved memory r= egions + * fdt_init_reserved_mem_node() - Initialize a reserved memory region + * @node: fdt node for the region to be initialized. + * @uname: name of the region to be initialized. + * @base: base address of the region to be initialized. + * @size: size of the region to be initialized. + * + * This function is used to call the region specific initialization + * function on a reserved memory region described by the node, name, + * base address and size being passed in as arguments. */ -void __init fdt_init_reserved_mem(void) +static void __init fdt_init_reserved_mem_node(unsigned long node, const ch= ar *uname, + phys_addr_t base, phys_addr_t size) { - int i; - - /* check for overlapping reserved regions */ - __rmem_check_for_overlap(); - - for (i =3D 0; i < reserved_mem_count; i++) { - struct reserved_mem *rmem =3D &reserved_mem[i]; - unsigned long node =3D rmem->fdt_node; - int err =3D 0; - bool nomap; + int err =3D 0; + bool nomap; + struct reserved_mem rmem =3D { + .fdt_node =3D node, + .name =3D uname, + .base =3D base, + .size =3D size + }; =20 - nomap =3D of_get_flat_dt_prop(node, "no-map", NULL) !=3D NULL; + nomap =3D of_get_flat_dt_prop(node, "no-map", NULL) !=3D NULL; =20 - if (rmem->size =3D=3D 0) - err =3D __reserved_mem_alloc_size(node, rmem->name, - &rmem->base, &rmem->size); - if (err =3D=3D 0) { - err =3D __reserved_mem_init_node(rmem); - if (err !=3D 0 && err !=3D -ENOENT) { - pr_info("node %s compatible matching fail\n", - rmem->name); - if (nomap) - memblock_clear_nomap(rmem->base, rmem->size); - else - memblock_phys_free(rmem->base, - rmem->size); - } else { - phys_addr_t end =3D rmem->base + rmem->size - 1; - bool reusable =3D - (of_get_flat_dt_prop(node, "reusable", NULL)) !=3D NULL; - - pr_info("%pa..%pa (%lu KiB) %s %s %s\n", - &rmem->base, &end, (unsigned long)(rmem->size / SZ_1K), - nomap ? "nomap" : "map", - reusable ? "reusable" : "non-reusable", - rmem->name ? rmem->name : "unknown"); - } - } + err =3D __reserved_mem_init_node(&rmem); + if (err !=3D 0 && err !=3D -ENOENT) { + pr_info("node %s compatible matching fail\n", rmem.name); + if (nomap) + memblock_clear_nomap(rmem.base, rmem.size); + else + memblock_phys_free(rmem.base, rmem.size); + } else { + phys_addr_t end =3D rmem.base + rmem.size - 1; + bool reusable =3D + (of_get_flat_dt_prop(node, "reusable", NULL)) !=3D NULL; + + pr_info("%pa..%pa (%lu KiB) %s %s %s\n", + &rmem.base, &end, (unsigned long)(rmem.size / SZ_1K), + nomap ? "nomap" : "map", + reusable ? "reusable" : "non-reusable", + rmem.name ? rmem.name : "unknown"); } } =20 --=20 2.34.1 From nobody Fri Dec 19 07:21:28 2025 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4198C1BA279; Fri, 30 Aug 2024 16:29:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725035399; cv=none; b=OyTtkc6dE8Of9k0nPf8IpFigwtb/s3GPSkEtzmG8JCyFQ+ZXkyjBBAw+q09vGRmCEAQ5JAbJOuJ4ON/CL7+oSKcVsWujWmJF8131X3tLEOpZEX1RD22Jn5eczSQEXRMS6IPVcg/AeKDnmrK45/TkGpzJDQnRGEU96eLg89kVGwY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1725035399; c=relaxed/simple; bh=Sca1w6+M1Fa4xga2IU+7IGr5WdrMm9HCmGgNEibQRIs=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UohiKoYduEylZyAOYM8nzC1D8jo+Ye+t5U9yX3plj31NDUZRyisQpH2fq9vbrQFHvTdoBQ1g0gicF0MCQzvSKQJuvmSswa8VVy92wezLqCthNMNTUvLYFbZgx0DlkKllRVRtL3E0mOcVdSKo8o9Z0mObFj8h/kON/+VkZ66zTBw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=K7BEYuBh; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="K7BEYuBh" Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 47UFBfMW010668; Fri, 30 Aug 2024 16:29:35 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= QDcyp35+X/FDNH02/gmXctPetcl8NyWSGu4roXmGmf8=; b=K7BEYuBhPKxRDY8f FDEAwmhyIwby7EXcUE6+AqeLvM8fiovzyCNjW/V/i24cwKhlNYyhUYjGu6d/aDgv Ltv2S1NWtuFyNF1LoPhnryJs93JuBdInIanaPPACPcMVs7S5XO38LPW79qagv80/ oJ8HgtSXt/eTieOPgQbsEGLNs1qDaFIbHFb4IEy520mc27im25o1/CQGOnk6Iw/+ EyVWv6yxMjNVN36UiFl3SPBTMtLnj2qu2vx/AqhJCVS8B732VA19pn+yV9hQ9CFA fPVW1b3lGE6MfqrHdk3E4+vhO9IFWK5CJS1b6JCa/s5by0qx5medVKd/MXK74gUS vCSPng== Received: from nalasppmta04.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 419pv0spr1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 30 Aug 2024 16:29:35 +0000 (GMT) Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com [10.47.209.197]) by NALASPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 47UGTXYC011671 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 30 Aug 2024 16:29:33 GMT Received: from hu-obabatun-lv.qualcomm.com (10.49.16.6) by nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Fri, 30 Aug 2024 09:29:30 -0700 From: Oreoluwa Babatunde To: CC: , , , , , , , , , , , , , Subject: [PATCH v8 2/2] of: reserved_mem: Add code to dynamically allocate reserved_mem array Date: Fri, 30 Aug 2024 09:28:57 -0700 Message-ID: <20240830162857.2821502-3-quic_obabatun@quicinc.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240830162857.2821502-1-quic_obabatun@quicinc.com> References: <20240830162857.2821502-1-quic_obabatun@quicinc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: nalasex01c.na.qualcomm.com (10.47.97.35) To nalasex01b.na.qualcomm.com (10.47.209.197) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: 7erGiJ-mlvAvMBf9NB_2-aAoi1xa05Wm X-Proofpoint-ORIG-GUID: 7erGiJ-mlvAvMBf9NB_2-aAoi1xa05Wm X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-08-30_10,2024-08-30_01,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 mlxlogscore=999 bulkscore=0 impostorscore=0 phishscore=0 clxscore=1015 mlxscore=0 spamscore=0 suspectscore=0 malwarescore=0 adultscore=0 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2407110000 definitions=main-2408300126 Content-Type: text/plain; charset="utf-8" The reserved_mem array is statically allocated with a size of MAX_RESERVED_REGIONS(64). Therefore, if the number of reserved_mem regions exceeds this size, there will not be enough space to store all the data. Hence, extend the use of the static array by introducing a dynamically allocated array based on the number of reserved memory regions specified in the DT. On architectures such as arm64, memblock allocated memory is not writable until after the page tables have been setup. Hence, the dynamic allocation of the reserved_mem array will need to be done only after the page tables have been setup. As a result, a temporary static array is still needed in the initial stages to store the information of the dynamically-placed reserved memory regions because the start address is selected only at run-time and is not stored anywhere else. It is not possible to wait until the reserved_mem array is allocated because this is done after the page tables are setup and the reserved memory regions need to be initialized before then. After the reserved_mem array is allocated, all entries from the static array is copied over to the new array, and the rest of the information for the statically-placed reserved memory regions are read in from the DT and stored in the new array as well. Once the init process is completed, the temporary static array is released back to the system because it is no longer needed. This is achieved by marking it as __initdata. Signed-off-by: Oreoluwa Babatunde Tested-by: Klara Modin Tested-by: Ninad Naik # sa8775p-ride --- drivers/of/of_reserved_mem.c | 68 +++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index a4487ee6c5ca..7452a2af7f1b 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -27,7 +27,9 @@ =20 #include "of_private.h" =20 -static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; +static struct reserved_mem reserved_mem_array[MAX_RESERVED_REGIONS] __init= data; +static struct reserved_mem *reserved_mem __refdata =3D reserved_mem_array; +static int total_reserved_mem_cnt =3D MAX_RESERVED_REGIONS; static int reserved_mem_count; =20 static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t siz= e, @@ -55,6 +57,50 @@ static int __init early_init_dt_alloc_reserved_memory_ar= ch(phys_addr_t size, return err; } =20 +/* + * alloc_reserved_mem_array() - allocate memory for the reserved_mem + * array using memblock + * + * This function is used to allocate memory for the reserved_mem + * array according to the total number of reserved memory regions + * defined in the DT. + * After the new array is allocated, the information stored in + * the initial static array is copied over to this new array and + * the new array is used from this point on. + */ +static void __init alloc_reserved_mem_array(void) +{ + struct reserved_mem *new_array; + size_t alloc_size, copy_size, memset_size; + + alloc_size =3D array_size(total_reserved_mem_cnt, sizeof(*new_array)); + if (alloc_size =3D=3D SIZE_MAX) { + pr_err("Failed to allocate memory for reserved_mem array with err: %d", = -EOVERFLOW); + return; + } + + new_array =3D memblock_alloc(alloc_size, SMP_CACHE_BYTES); + if (!new_array) { + pr_err("Failed to allocate memory for reserved_mem array with err: %d", = -ENOMEM); + return; + } + + copy_size =3D array_size(reserved_mem_count, sizeof(*new_array)); + if (copy_size =3D=3D SIZE_MAX) { + memblock_free(new_array, alloc_size); + total_reserved_mem_cnt =3D MAX_RESERVED_REGIONS; + pr_err("Failed to allocate memory for reserved_mem array with err: %d", = -EOVERFLOW); + return; + } + + memset_size =3D alloc_size - copy_size; + + memcpy(new_array, reserved_mem, copy_size); + memset(new_array + reserved_mem_count, 0, memset_size); + + reserved_mem =3D new_array; +} + /* * fdt_reserved_mem_save_node() - save fdt node for second pass initializa= tion */ @@ -63,7 +109,7 @@ static void __init fdt_reserved_mem_save_node(unsigned l= ong node, const char *un { struct reserved_mem *rmem =3D &reserved_mem[reserved_mem_count]; =20 - if (reserved_mem_count =3D=3D ARRAY_SIZE(reserved_mem)) { + if (reserved_mem_count =3D=3D total_reserved_mem_cnt) { pr_err("not enough space for all defined regions.\n"); return; } @@ -202,6 +248,13 @@ void __init fdt_scan_reserved_mem_reg_nodes(void) return; } =20 + /* + * Allocate the exact size needed for the reserved_mem array and + * copy all the contents from the previous array if allocation + * is successful. + */ + alloc_reserved_mem_array(); + fdt_for_each_subnode(child, fdt, node) { const char *uname; =20 @@ -236,7 +289,7 @@ static int __init __reserved_mem_alloc_size(unsigned lo= ng node, const char *unam int __init fdt_scan_reserved_mem(void) { int node, child; - int dynamic_nodes_cnt =3D 0; + int dynamic_nodes_cnt =3D 0, count =3D 0; int dynamic_nodes[MAX_RESERVED_REGIONS]; const void *fdt =3D initial_boot_params; =20 @@ -259,6 +312,9 @@ int __init fdt_scan_reserved_mem(void) uname =3D fdt_get_name(fdt, child, NULL); =20 err =3D __reserved_mem_reserve_reg(child, uname); + if (!err) + count++; + /* * Save the nodes for the dynamically-placed regions * into an array which will be used for allocation right @@ -273,11 +329,15 @@ int __init fdt_scan_reserved_mem(void) } for (int i =3D 0; i < dynamic_nodes_cnt; i++) { const char *uname; + int err; =20 child =3D dynamic_nodes[i]; uname =3D fdt_get_name(fdt, child, NULL); - __reserved_mem_alloc_size(child, uname); + err =3D __reserved_mem_alloc_size(child, uname); + if (!err) + count++; } + total_reserved_mem_cnt =3D count; return 0; } =20 --=20 2.34.1