From nobody Fri Dec 19 20:13:58 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1673604729; cv=none; d=zohomail.com; s=zohoarc; b=h69jJN0JZc5F0J7i2zsplpx3U6mCoep8gzWo9gub9A0Tt+qG1cKdRdjw0EYUXAbXQg6t+MOCVK9Xm5Fqnjh3E0+HN6u17CCc3B1W+drqGuDyZGpLdfnYfZmd3Zz5vkZzN/V7QAY9MeGF4x2A9q6CfcN4QN4mFwwpOCNYQpX6Yc0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673604729; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=NC2ekxnVww5wg4SYyZ+ZoYGc9aeqnQEz5JZ2U/1m/VM=; b=Cs86w391Z6KcXLbYV0Ys7z4oDSKwuk84SruvrEKHnp2Xstaket4Y5UfJIQ3lMEbA/ukKxSc/XLekQ1BoWqbK/S+XFw9rb2Uj9NmyDXDXfGAQlc8RwBggnOWsSiF/b0HVkayQhV8q/5myXUHqRhNL9GSSgRNpvKmadHp8d0T0MQE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1673604729533186.7766480320331; Fri, 13 Jan 2023 02:12:09 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.477055.739651 (Exim 4.92) (envelope-from ) id 1pGH2O-0005y5-4V; Fri, 13 Jan 2023 10:11:52 +0000 Received: by outflank-mailman (output) from mailman id 477055.739651; Fri, 13 Jan 2023 10:11:52 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1pGH2N-0005vn-MO; Fri, 13 Jan 2023 10:11:51 +0000 Received: by outflank-mailman (input) for mailman id 477055; Fri, 13 Jan 2023 10:11:50 +0000 Received: from mail.xenproject.org ([104.130.215.37]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1pGH2M-0005kJ-Qu for xen-devel@lists.xenproject.org; Fri, 13 Jan 2023 10:11:50 +0000 Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1pGH2M-0006f1-Od; Fri, 13 Jan 2023 10:11:50 +0000 Received: from 54-240-197-224.amazon.com ([54.240.197.224] helo=dev-dsk-jgrall-1b-035652ec.eu-west-1.amazon.com) by xenbits.xenproject.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1pGH2M-0005Ty-DI; Fri, 13 Jan 2023 10:11:50 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version 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" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=xen.org; s=20200302mail; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=NC2ekxnVww5wg4SYyZ+ZoYGc9aeqnQEz5JZ2U/1m/VM=; b=N8m9sAtxqZPbFvAI9ThWmffC/t WGk+5ykLdBpoKsZ1JhTePi1n/rE0HYYbXj3b76eqca/GLEU6DrIQkWHQ7s3qGz79fGKdv0ECQUZlL oB0Teq27B2bfp4avx+fGhWLiGdV5fmf0XKLpt6RC1efFEv9PyoNMjJ2s20OKn0eVcZN4=; From: Julien Grall To: xen-devel@lists.xenproject.org Cc: Luca.Fancellu@arm.com, Julien Grall , Stefano Stabellini , Julien Grall , Bertrand Marquis , Volodymyr Babchuk Subject: [PATCH v4 09/14] xen/arm32: head: Remove restriction where to load Xen Date: Fri, 13 Jan 2023 10:11:31 +0000 Message-Id: <20230113101136.479-10-julien@xen.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230113101136.479-1-julien@xen.org> References: <20230113101136.479-1-julien@xen.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @xen.org) X-ZM-MESSAGEID: 1673604729858100015 Content-Type: text/plain; charset="utf-8" From: Julien Grall At the moment, bootloaders can load Xen anywhere in memory but the region 2MB - 4MB. While I am not aware of any issue, we have no way to tell the bootloader to avoid that region. In addition to that, in the future, Xen may grow over 2MB if we enable feature like UBSAN or GCOV. To avoid widening the restriction on the load address, it would be better to get rid of it. When the identity mapping is clashing with the Xen runtime mapping, we need an extra indirection to be able to replace the identity mapping with the Xen runtime mapping. Reserve a new memory region that will be used to temporarily map Xen. For convenience, the new area is re-using the same first slot as the domheap which is used for per-cpu temporary mapping after a CPU has booted. Furthermore, directly map boot_second (which cover Xen and more) to the temporary area. This will avoid to allocate an extra page-table for the second-level and will helpful for follow-up patches (we will want to use the fixmap whilst in the temporary mapping). Lastly, some part of the code now needs to know whether the temporary mapping was created. So reserve r12 to store this information. Signed-off-by: Julien Grall Reviewed-by: Luca Fancellu Reviewed-by: Michal Orzel Tested-by: Luca Fancellu ---- Changes in v4: - Remove spurious newline Changes in v3: - Remove the ASSERT() in init_domheap_mappings() because it was bogus (secondary CPU root tables are initialized to the CPU0 root table so the entry will be valid). Also, it is not related to this patch as the CPU0 root table are rebuilt during boot. The ASSERT() will be re-introduced later. Changes in v2: - Patch added --- xen/arch/arm/arm32/head.S | 139 ++++++++++++++++++++++++++---- xen/arch/arm/include/asm/config.h | 14 +++ xen/arch/arm/mm.c | 14 +++ 3 files changed, 152 insertions(+), 15 deletions(-) diff --git a/xen/arch/arm/arm32/head.S b/xen/arch/arm/arm32/head.S index 67b910808b74..3800efb44169 100644 --- a/xen/arch/arm/arm32/head.S +++ b/xen/arch/arm/arm32/head.S @@ -35,6 +35,9 @@ #define XEN_FIRST_SLOT first_table_offset(XEN_VIRT_START) #define XEN_SECOND_SLOT second_table_offset(XEN_VIRT_START) =20 +/* Offset between the early boot xen mapping and the runtime xen mapping */ +#define XEN_TEMPORARY_OFFSET (TEMPORARY_XEN_VIRT_START - XEN_VIRT_STA= RT) + #if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_EARLY_PRINTK_INC) #include CONFIG_EARLY_PRINTK_INC #endif @@ -94,7 +97,7 @@ * r9 - paddr(start) * r10 - phys offset * r11 - UART address - * r12 - + * r12 - Temporary mapping created * r13 - SP * r14 - LR * r15 - PC @@ -445,6 +448,9 @@ ENDPROC(cpu_init) * r9 : paddr(start) * r10: phys offset * + * Output: + * r12: Was a temporary mapping created? + * * Clobbers r0 - r4, r6 * * Register usage within this function: @@ -484,7 +490,11 @@ create_page_tables: /* * Setup the 1:1 mapping so we can turn the MMU on. Note that * only the first page of Xen will be part of the 1:1 mapping. + * + * In all the cases, we will link boot_third_id. So create the + * mapping in advance. */ + create_mapping_entry boot_third_id, r9, r9 =20 /* * Find the first slot used. If the slot is not XEN_FIRST_SLOT, @@ -501,8 +511,7 @@ create_page_tables: /* * Find the second slot used. If the slot is XEN_SECOND_SLOT, then= the * 1:1 mapping will use its own set of page-tables from the - * third level. For slot XEN_SECOND_SLOT, Xen is not yet able to h= andle - * it. + * third level. */ get_table_slot r1, r9, 2 /* r1 :=3D second slot */ cmp r1, #XEN_SECOND_SLOT @@ -513,13 +522,33 @@ create_page_tables: link_from_second_id: create_table_entry boot_second_id, boot_third_id, r9, 2 link_from_third_id: - create_mapping_entry boot_third_id, r9, r9 + /* Good news, we are not clashing with Xen virtual mapping */ + mov r12, #0 /* r12 :=3D temporary mapping not cre= ated */ mov pc, lr =20 virtphys_clash: - /* Identity map clashes with boot_third, which we cannot handle ye= t */ - PRINT("- Unable to build boot page tables - virt and phys addresse= s clash. -\r\n") - b fail + /* + * The identity map clashes with boot_third. Link boot_first_id and + * map Xen to a temporary mapping. See switch_to_runtime_mapping + * for more details. + */ + PRINT("- Virt and Phys addresses clash -\r\n") + PRINT("- Create temporary mapping -\r\n") + + /* + * This will override the link to boot_second in XEN_FIRST_SLOT. + * The page-tables are not live yet. So no need to use + * break-before-make. + */ + create_table_entry boot_pgtable, boot_second_id, r9, 1 + create_table_entry boot_second_id, boot_third_id, r9, 2 + + /* Map boot_second (cover Xen mappings) to the temporary 1st slot = */ + mov_w r0, TEMPORARY_XEN_VIRT_START + create_table_entry boot_pgtable, boot_second, r0, 1 + + mov r12, #1 /* r12 :=3D temporary mapping created= */ + mov pc, lr ENDPROC(create_page_tables) =20 /* @@ -528,9 +557,10 @@ ENDPROC(create_page_tables) * * Inputs: * r9 : paddr(start) + * r12 : Was the temporary mapping created? * lr : Virtual address to return to * - * Clobbers r0 - r3 + * Clobbers r0 - r5 */ enable_mmu: PRINT("- Turning on paging -\r\n") @@ -558,21 +588,79 @@ enable_mmu: * The MMU is turned on and we are in the 1:1 mapping. Switch * to the runtime mapping. */ - mov_w r0, 1f - mov pc, r0 + mov r5, lr /* Save LR before overwritting it */ + mov_w lr, 1f /* Virtual address in the runtime mapp= ing */ + b switch_to_runtime_mapping 1: + mov lr, r5 /* Restore LR */ /* - * The 1:1 map may clash with other parts of the Xen virtual memory - * layout. As it is not used anymore, remove it completely to - * avoid having to worry about replacing existing mapping - * afterwards. + * At this point, either the 1:1 map or the temporary mapping + * will be present. The former may clash with other parts of the + * Xen virtual memory layout. As both of them are not used + * anymore, remove them completely to avoid having to worry + * about replacing existing mapping afterwards. * * On return this will jump to the virtual address requested by * the caller. */ - b remove_identity_mapping + teq r12, #0 + beq remove_identity_mapping + b remove_temporary_mapping ENDPROC(enable_mmu) =20 +/* + * Switch to the runtime mapping. The logic depends on whether the + * runtime virtual region is clashing with the physical address + * + * - If it is not clashing, we can directly jump to the address in + * the runtime mapping. + * - If it is clashing, create_page_tables() would have mapped Xen to + * a temporary virtual address. We need to switch to the temporary + * mapping so we can remove the identity mapping and map Xen at the + * correct position. + * + * Inputs + * r9: paddr(start) + * r12: Was a temporary mapping created? + * lr: Address in the runtime mapping to jump to + * + * Clobbers r0 - r4 + */ +switch_to_runtime_mapping: + /* + * Jump to the runtime mapping if the virt and phys are not + * clashing + */ + teq r12, #0 + beq ready_to_switch + + /* We are still in the 1:1 mapping. Jump to the temporary Virtual = address. */ + mov_w r0, 1f + add r0, r0, #XEN_TEMPORARY_OFFSET /* r0 :=3D address in temporar= y mapping */ + mov pc, r0 + +1: + /* Remove boot_second_id */ + mov r2, #0 + mov r3, #0 + adr_l r0, boot_pgtable + get_table_slot r1, r9, 1 /* r1 :=3D first slot */ + lsl r1, r1, #3 /* r1 :=3D first slot offset */ + strd r2, r3, [r0, r1] + + flush_xen_tlb_local r0 + + /* Map boot_second into boot_pgtable */ + mov_w r0, XEN_VIRT_START + create_table_entry boot_pgtable, boot_second, r0, 1 + + /* Ensure any page table updates are visible before continuing */ + dsb nsh + +ready_to_switch: + mov pc, lr +ENDPROC(switch_to_runtime_mapping) + /* * Remove the 1:1 map from the page-tables. It is not easy to keep track * where the 1:1 map was mapped, so we will look for the top-level entry @@ -618,6 +706,27 @@ identity_mapping_removed: mov pc, lr ENDPROC(remove_identity_mapping) =20 +/* + * Remove the temporary mapping of Xen starting at TEMPORARY_XEN_VIRT_STAR= T. + * + * Clobbers r0 - r1 + */ +remove_temporary_mapping: + /* r2:r3 :=3D invalid page-table entry */ + mov r2, #0 + mov r3, #0 + + adr_l r0, boot_pgtable + mov_w r1, TEMPORARY_XEN_VIRT_START + get_table_slot r1, r1, 1 /* r1 :=3D first slot */ + lsl r1, r1, #3 /* r1 :=3D first slot offset */ + strd r2, r3, [r0, r1] + + flush_xen_tlb_local r0 + + mov pc, lr +ENDPROC(remove_temporary_mapping) + /* * Map the UART in the fixmap (when earlyprintk is used) and hook the * fixmap table in the page tables. diff --git a/xen/arch/arm/include/asm/config.h b/xen/arch/arm/include/asm/c= onfig.h index 87851e677701..6c1b762e976d 100644 --- a/xen/arch/arm/include/asm/config.h +++ b/xen/arch/arm/include/asm/config.h @@ -148,6 +148,20 @@ /* Number of domheap pagetable pages required at the second level (2MB map= pings) */ #define DOMHEAP_SECOND_PAGES (DOMHEAP_VIRT_SIZE >> FIRST_SHIFT) =20 +/* + * The temporary area is overlapping with the domheap area. This may + * be used to create an alias of the first slot containing Xen mappings + * when turning on/off the MMU. + */ +#define TEMPORARY_AREA_FIRST_SLOT (first_table_offset(DOMHEAP_VIRT_STAR= T)) + +/* Calculate the address in the temporary area */ +#define TEMPORARY_AREA_ADDR(addr) \ + (((addr) & ~XEN_PT_LEVEL_MASK(1)) | \ + (TEMPORARY_AREA_FIRST_SLOT << XEN_PT_LEVEL_SHIFT(1))) + +#define TEMPORARY_XEN_VIRT_START TEMPORARY_AREA_ADDR(XEN_VIRT_START) + #else /* ARM_64 */ =20 #define SLOT0_ENTRY_BITS 39 diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 0fc6f2992dd1..9ebc2d0f609e 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -167,6 +167,9 @@ static void __init __maybe_unused build_assertions(void) #define CHECK_SAME_SLOT(level, virt1, virt2) \ BUILD_BUG_ON(level##_table_offset(virt1) !=3D level##_table_offset(vir= t2)) =20 +#define CHECK_DIFFERENT_SLOT(level, virt1, virt2) \ + BUILD_BUG_ON(level##_table_offset(virt1) =3D=3D level##_table_offset(v= irt2)) + #ifdef CONFIG_ARM_64 CHECK_SAME_SLOT(zeroeth, XEN_VIRT_START, FIXMAP_ADDR(0)); CHECK_SAME_SLOT(zeroeth, XEN_VIRT_START, BOOT_FDT_VIRT_START); @@ -174,7 +177,18 @@ static void __init __maybe_unused build_assertions(voi= d) CHECK_SAME_SLOT(first, XEN_VIRT_START, FIXMAP_ADDR(0)); CHECK_SAME_SLOT(first, XEN_VIRT_START, BOOT_FDT_VIRT_START); =20 + /* + * For arm32, the temporary mapping will re-use the domheap + * first slot and the second slots will match. + */ +#ifdef CONFIG_ARM_32 + CHECK_SAME_SLOT(first, TEMPORARY_XEN_VIRT_START, DOMHEAP_VIRT_START); + CHECK_DIFFERENT_SLOT(first, XEN_VIRT_START, TEMPORARY_XEN_VIRT_START); + CHECK_SAME_SLOT(second, XEN_VIRT_START, TEMPORARY_XEN_VIRT_START); +#endif + #undef CHECK_SAME_SLOT +#undef CHECK_DIFFERENT_SLOT } =20 static lpae_t *xen_map_table(mfn_t mfn) --=20 2.38.1