From mboxrd@z Thu Jan 1 00:00:00 1970 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.3 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_SANE_1 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 5BE81C433ED for ; Fri, 9 Apr 2021 11:40:08 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 9D1FE6115C for ; Fri, 9 Apr 2021 11:40:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9D1FE6115C Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=ghiti.fr Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 38C768D0002; Fri, 9 Apr 2021 07:40:07 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 33BF16B0070; Fri, 9 Apr 2021 07:40:07 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 1673A8D0002; Fri, 9 Apr 2021 07:40:07 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id DE0226B006E for ; Fri, 9 Apr 2021 07:40:06 -0400 (EDT) Received: from smtpin35.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id 915711845F483 for ; Fri, 9 Apr 2021 11:40:06 +0000 (UTC) X-FDA: 78012634812.35.75CFAE7 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) by imf05.hostedemail.com (Postfix) with ESMTP id CBA27E000108 for ; Fri, 9 Apr 2021 11:40:04 +0000 (UTC) X-Originating-IP: 82.65.183.113 Received: from [172.16.5.113] (82-65-183-113.subs.proxad.net [82.65.183.113]) (Authenticated sender: alex@ghiti.fr) by relay4-d.mail.gandi.net (Postfix) with ESMTPSA id 516F9E0002; Fri, 9 Apr 2021 11:39:59 +0000 (UTC) Subject: Re: [PATCH v7] RISC-V: enable XIP To: David Hildenbrand , Paul Walmsley , Palmer Dabbelt , Albert Ou , linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org, linux-mm@kvack.org Cc: Vitaly Wool , Mike Rapoport References: <20210409065115.11054-1-alex@ghiti.fr> <3500f3cb-b660-5bbc-ae8d-0c9770e4a573@ghiti.fr> From: Alex Ghiti Message-ID: Date: Fri, 9 Apr 2021 07:39:59 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.9.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: fr X-Rspamd-Server: rspam01 X-Rspamd-Queue-Id: CBA27E000108 X-Stat-Signature: zjfso3xhwaznb5tfafeu6r73r1gz5efz Received-SPF: none (ghiti.fr>: No applicable sender policy available) receiver=imf05; identity=mailfrom; envelope-from=""; helo=relay4-d.mail.gandi.net; client-ip=217.70.183.196 X-HE-DKIM-Result: none/none X-HE-Tag: 1617968404-503834 Content-Transfer-Encoding: quoted-printable X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Hi David, Le 4/9/21 =C3=A0 4:23 AM, David Hildenbrand a =C3=A9crit=C2=A0: > On 09.04.21 09:14, Alex Ghiti wrote: >> Le 4/9/21 =C3=A0 2:51 AM, Alexandre Ghiti a =C3=A9crit=C2=A0: >>> From: Vitaly Wool >>> >>> Introduce XIP (eXecute In Place) support for RISC-V platforms. >>> It allows code to be executed directly from non-volatile storage >>> directly addressable by the CPU, such as QSPI NOR flash which can >>> be found on many RISC-V platforms. This makes way for significant >>> optimization of RAM footprint. The XIP kernel is not compressed >>> since it has to run directly from flash, so it will occupy more >>> space on the non-volatile storage. The physical flash address used >>> to link the kernel object files and for storing it has to be known >>> at compile time and is represented by a Kconfig option. >>> >>> XIP on RISC-V will for the time being only work on MMU-enabled >>> kernels. >>> >> I added linux-mm and linux-arch to get feedbacks because I noticed tha= t >> DEBUG_VM_PGTABLE fails for SPARSEMEM (it works for FLATMEM but I think >> it does not do what is expected): the fact that we don't have any stru= ct >> page to back the text and rodata in flash is the problem but to which >> extent ? >=20 > Just wondering, why can't we create a memmap for that memory -- or is i= t=20 > even desireable to not do that explicity? There might be some nasty sid= e=20 > effects when not having a memmap for text and rodata. Do you have examples of such effects ? Any feature that will not work=20 without that ? >=20 > I would assume stimply exposing the physical memory range to memblock a= s=20 > RAM and marking it reserved would create a memmap that's fully=20 > initialized like any bootmem (PG_reserved). >=20 > Or is there a reason why we cannot do that? I did not want to do that if it was not needed as the overall goal of=20 XIP kernel is to save RAM (I may be cheap but 16MB backed by struct page=20 represents ~220KB). >=20 > Also, will that memory properly be exposed in the resource tree as=20 > System RAM (e.g., /proc/iomem) ? Otherwise some things (/proc/kcore)=20 > won't work as expected - the kernel won't be included in a dump. I have just checked and it does not appear in /proc/iomem. Ok your conclusion would be to have struct page, I'm going to implement=20 this version then using memblock as you described. Thanks David, Alex >=20 >=20 >> >> Thanks, >> >> Alex >> >>> Signed-off-by: Alexandre Ghiti [ Rebase on top of "Mo= ve >>> kernel mapping outside the linear mapping=C2=A0] >>> Signed-off-by: Vitaly Wool >>> --- >>> >>> Changes in v2: >>> - dedicated macro for XIP address fixup when MMU is not enabled yet >>> =C2=A0=C2=A0=C2=A0 o both for 32-bit and 64-bit RISC-V >>> - SP is explicitly set to a safe place in RAM before __copy_data call >>> - removed redundant alignment requirements in vmlinux-xip.lds.S >>> - changed long -> uintptr_t typecast in __XIP_FIXUP macro. >>> Changes in v3: >>> - rebased against latest for-next >>> - XIP address fixup macro now takes an argument >>> - SMP related fixes >>> Changes in v4: >>> - rebased against the current for-next >>> - less #ifdef's in C/ASM code >>> - dedicated XIP_FIXUP_OFFSET assembler macro in head.S >>> - C-specific definitions moved into #ifndef __ASSEMBLY__ >>> - Fixed multi-core boot >>> Changes in v5: >>> - fixed build error for non-XIP kernels >>> Changes in v6: >>> - XIP_PHYS_RAM_BASE config option renamed to PHYS_RAM_BASE >>> - added PHYS_RAM_BASE_FIXED config flag to allow usage of >>> =C2=A0=C2=A0=C2=A0 PHYS_RAM_BASE in non-XIP configurations if needed >>> - XIP_FIXUP macro rewritten with a tempoarary variable to avoid side >>> =C2=A0=C2=A0=C2=A0 effects >>> - fixed crash for non-XIP kernels that don't use built-in DTB >>> Changes in v7: >>> - Fix pfn_base that required FIXUP >>> - Fix copy_data which lacked + 1 in size to copy >>> - Fix pfn_valid for FLATMEM >>> - Rebased on top of "Move kernel mapping outside the linear mapping": >>> =C2=A0=C2=A0=C2=A0 this is the biggest change and affected mm/init.c, >>> =C2=A0=C2=A0=C2=A0 kernel/vmlinux-xip.lds.S and include/asm/pgtable.h= : XIP kernel is=20 >>> now >>> =C2=A0=C2=A0=C2=A0 mapped like 'normal' kernel at the end of the addr= ess space. >>> >>> =C2=A0=C2=A0 arch/riscv/Kconfig=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0 5= 1 ++++++++++- >>> =C2=A0=C2=A0 arch/riscv/Makefile=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0 8= +- >>> =C2=A0=C2=A0 arch/riscv/boot/Makefile=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0 13 +++ >>> =C2=A0=C2=A0 arch/riscv/include/asm/page.h=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 |=C2=A0 28 ++++++ >>> =C2=A0=C2=A0 arch/riscv/include/asm/pgtable.h=C2=A0=C2=A0=C2=A0 |=C2=A0= 25 +++++- >>> =C2=A0=C2=A0 arch/riscv/kernel/head.S=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0 46 +++++++++- >>> =C2=A0=C2=A0 arch/riscv/kernel/head.h=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0=C2=A0 3 + >>> =C2=A0=C2=A0 arch/riscv/kernel/setup.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0 10 ++- >>> =C2=A0=C2=A0 arch/riscv/kernel/vmlinux-xip.lds.S | 133=20 >>> ++++++++++++++++++++++++++++ >>> =C2=A0=C2=A0 arch/riscv/kernel/vmlinux.lds.S=C2=A0=C2=A0=C2=A0=C2=A0 = |=C2=A0=C2=A0 6 ++ >>> =C2=A0=C2=A0 arch/riscv/mm/init.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 118 ++++++++++++= ++++++++++-- >>> =C2=A0=C2=A0 11 files changed, 424 insertions(+), 17 deletions(-) >>> =C2=A0=C2=A0 create mode 100644 arch/riscv/kernel/vmlinux-xip.lds.S >>> >>> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig >>> index 8ea60a0a19ae..4d0153805927 100644 >>> --- a/arch/riscv/Kconfig >>> +++ b/arch/riscv/Kconfig >>> @@ -28,7 +28,7 @@ config RISCV >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_PTE_SPECIAL >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_SET_DIRECT_MAP >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_SET_MEMORY >>> -=C2=A0=C2=A0=C2=A0 select ARCH_HAS_STRICT_KERNEL_RWX if MMU >>> +=C2=A0=C2=A0=C2=A0 select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_= KERNEL >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_HAS_TICK_BROADCAST i= f GENERIC_CLOCKEVENTS_BROADCAST >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_OPTIONAL_KERNEL_RWX = if ARCH_HAS_STRICT_KERNEL_RWX >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select ARCH_OPTIONAL_KERNEL_RWX_= DEFAULT >>> @@ -441,7 +441,7 @@ config EFI_STUB >>> =C2=A0=C2=A0 config EFI >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 bool "UEFI runtime support" >>> -=C2=A0=C2=A0=C2=A0 depends on OF >>> +=C2=A0=C2=A0=C2=A0 depends on OF && !XIP_KERNEL >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select LIBFDT >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select UCS2_STRING >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 select EFI_PARAMS_FROM_FDT >>> @@ -465,11 +465,56 @@ config STACKPROTECTOR_PER_TASK >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 def_bool y >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 depends on STACKPROTECTOR && CC_= HAVE_STACKPROTECTOR_TLS >>> +config PHYS_RAM_BASE_FIXED >>> +=C2=A0=C2=A0=C2=A0 bool "Explicitly specified physical RAM address" >>> +=C2=A0=C2=A0=C2=A0 default n >>> + >>> +config PHYS_RAM_BASE >>> +=C2=A0=C2=A0=C2=A0 hex "Platform Physical RAM address" >>> +=C2=A0=C2=A0=C2=A0 depends on PHYS_RAM_BASE_FIXED >>> +=C2=A0=C2=A0=C2=A0 default "0x80000000" >>> +=C2=A0=C2=A0=C2=A0 help >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 This is the physical address of RAM i= n the system. It has to be >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 explicitly specified to run early rel= ocations of read-write data >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 from flash to RAM. >>> + >>> +config XIP_KERNEL >>> +=C2=A0=C2=A0=C2=A0 bool "Kernel Execute-In-Place from ROM" >>> +=C2=A0=C2=A0=C2=A0 depends on MMU >>> +=C2=A0=C2=A0=C2=A0 select PHYS_RAM_BASE_FIXED >>> +=C2=A0=C2=A0=C2=A0 help >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 Execute-In-Place allows the kernel to= run from non-volatile=20 >>> storage >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 directly addressable by the CPU, such= as NOR flash. This saves=20 >>> RAM >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 space since the text section of the k= ernel is not loaded from=20 >>> flash >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 to RAM.=C2=A0 Read-write sections, su= ch as the data section and stack, >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 are still copied to RAM.=C2=A0 The XI= P kernel is not compressed since >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 it has to run directly from flash, so= it will take more space to >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 store it.=C2=A0 The flash address use= d to link the kernel object=20 >>> files, >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 and for storing it, is configuration = dependent. Therefore, if you >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 say Y here, you must know the proper = physical address where to >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 store the kernel image depending on y= our own flash memory usage. >>> + >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 Also note that the make target become= s "make xipImage" rather=20 >>> than >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 "make zImage" or "make Image".=C2=A0 = The final kernel binary to put in >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ROM memory will be arch/riscv/boot/xi= pImage. >>> + >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 If unsure, say N. >>> + >>> +config XIP_PHYS_ADDR >>> +=C2=A0=C2=A0=C2=A0 hex "XIP Kernel Physical Location" >>> +=C2=A0=C2=A0=C2=A0 depends on XIP_KERNEL >>> +=C2=A0=C2=A0=C2=A0 default "0x21000000" >>> +=C2=A0=C2=A0=C2=A0 help >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 This is the physical address in your = flash memory the kernel will >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 be linked for and stored to.=C2=A0 Th= is address is dependent on your >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 own flash usage. >>> + >>> =C2=A0=C2=A0 endmenu >>> =C2=A0=C2=A0 config BUILTIN_DTB >>> -=C2=A0=C2=A0=C2=A0 def_bool n >>> +=C2=A0=C2=A0=C2=A0 bool >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 depends on OF >>> +=C2=A0=C2=A0=C2=A0 default y if XIP_KERNEL >>> =C2=A0=C2=A0 menu "Power management options" >>> diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile >>> index 1368d943f1f3..8fcbec03974d 100644 >>> --- a/arch/riscv/Makefile >>> +++ b/arch/riscv/Makefile >>> @@ -82,7 +82,11 @@ CHECKFLAGS +=3D -D__riscv -D__riscv_xlen=3D$(BITS) >>> =C2=A0=C2=A0 # Default target when executing plain make >>> =C2=A0=C2=A0 boot=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 :=3D arch= /riscv/boot >>> +ifeq ($(CONFIG_XIP_KERNEL),y) >>> +KBUILD_IMAGE :=3D $(boot)/xipImage >>> +else >>> =C2=A0=C2=A0 KBUILD_IMAGE=C2=A0=C2=A0=C2=A0 :=3D $(boot)/Image.gz >>> +endif >>> =C2=A0=C2=A0 head-y :=3D arch/riscv/kernel/head.o >>> @@ -95,12 +99,14 @@ PHONY +=3D vdso_install >>> =C2=A0=C2=A0 vdso_install: >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 $(Q)$(MAKE) $(build)=3Darch/risc= v/kernel/vdso $@ >>> +ifneq ($(CONFIG_XIP_KERNEL),y) >>> =C2=A0=C2=A0 ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_SOC_CANAAN),yy) >>> =C2=A0=C2=A0 KBUILD_IMAGE :=3D $(boot)/loader.bin >>> =C2=A0=C2=A0 else >>> =C2=A0=C2=A0 KBUILD_IMAGE :=3D $(boot)/Image.gz >>> =C2=A0=C2=A0 endif >>> -BOOT_TARGETS :=3D Image Image.gz loader loader.bin >>> +endif >>> +BOOT_TARGETS :=3D Image Image.gz loader loader.bin xipImage >>> =C2=A0=C2=A0 all:=C2=A0=C2=A0=C2=A0 $(notdir $(KBUILD_IMAGE)) >>> diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile >>> index 03404c84f971..6bf299f70c27 100644 >>> --- a/arch/riscv/boot/Makefile >>> +++ b/arch/riscv/boot/Makefile >>> @@ -17,8 +17,21 @@ >>> =C2=A0=C2=A0 KCOV_INSTRUMENT :=3D n >>> =C2=A0=C2=A0 OBJCOPYFLAGS_Image :=3D-O binary -R .note -R .note.gnu.b= uild-id -R=20 >>> .comment -S >>> +OBJCOPYFLAGS_xipImage :=3D-O binary -R .note -R .note.gnu.build-id -= R=20 >>> .comment -S >>> =C2=A0=C2=A0 targets :=3D Image Image.* loader loader.o loader.lds lo= ader.bin >>> +targets :=3D Image Image.* loader loader.o loader.lds loader.bin xip= Image >>> + >>> +ifeq ($(CONFIG_XIP_KERNEL),y) >>> + >>> +quiet_cmd_mkxip =3D $(quiet_cmd_objcopy) >>> +cmd_mkxip =3D $(cmd_objcopy) >>> + >>> +$(obj)/xipImage: vmlinux FORCE >>> +=C2=A0=C2=A0=C2=A0 $(call if_changed,mkxip) >>> +=C2=A0=C2=A0=C2=A0 @$(kecho) '=C2=A0 Physical Address of xipImage: $= (CONFIG_XIP_PHYS_ADDR)' >>> + >>> +endif >>> =C2=A0=C2=A0 $(obj)/Image: vmlinux FORCE >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 $(call if_changed,objcopy) >>> diff --git a/arch/riscv/include/asm/page.h=20 >>> b/arch/riscv/include/asm/page.h >>> index 22cfb2be60dc..6fe0ff8c8fa9 100644 >>> --- a/arch/riscv/include/asm/page.h >>> +++ b/arch/riscv/include/asm/page.h >>> @@ -91,6 +91,9 @@ typedef struct page *pgtable_t; >>> =C2=A0=C2=A0 #ifdef CONFIG_MMU >>> =C2=A0=C2=A0 extern unsigned long va_pa_offset; >>> =C2=A0=C2=A0 extern unsigned long va_kernel_pa_offset; >>> +#ifdef CONFIG_XIP_KERNEL >>> +extern unsigned long va_kernel_xip_pa_offset; >>> +#endif >>> =C2=A0=C2=A0 extern unsigned long pfn_base; >>> =C2=A0=C2=A0 #define ARCH_PFN_OFFSET=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 (pfn_base) >>> =C2=A0=C2=A0 #else >>> @@ -102,11 +105,29 @@ extern unsigned long pfn_base; >>> =C2=A0=C2=A0 extern unsigned long kernel_virt_addr; >>> =C2=A0=C2=A0 #define linear_mapping_pa_to_va(x)=C2=A0=C2=A0=C2=A0 ((v= oid *)((unsigned long)(x)=20 >>> + va_pa_offset)) >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define kernel_mapping_pa_to_va(y)=C2=A0=C2=A0=C2=A0 ({=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0 unsigned long _y =3D y;=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0 (_y >=3D CONFIG_PHYS_RAM_BASE) ?=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (void *)((unsigned long)(= _y) + va_kernel_pa_offset +=20 >>> XIP_OFFSET) :=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (void *)((unsigned long)(= _y) +=20 >>> va_kernel_xip_pa_offset);=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0 }) >>> +#else >>> =C2=A0=C2=A0 #define kernel_mapping_pa_to_va(x)=C2=A0=C2=A0=C2=A0 ((v= oid *)((unsigned long)(x)=20 >>> + va_kernel_pa_offset)) >>> +#endif >>> =C2=A0=C2=A0 #define __pa_to_va_nodebug(x)=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0 linear_mapping_pa_to_va(x) >>> =C2=A0=C2=A0 #define linear_mapping_va_to_pa(x)=C2=A0=C2=A0=C2=A0 ((u= nsigned long)(x) -=20 >>> va_pa_offset) >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define kernel_mapping_va_to_pa(y) ({=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0 unsigned long _y =3D y;=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0 (_y < kernel_virt_addr + XIP_OFFSET) ?=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ((unsigned long)(_y) - va= _kernel_xip_pa_offset) :=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ((unsigned long)(_y) - va= _kernel_pa_offset - XIP_OFFSET);=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0 }) >>> +#else >>> =C2=A0=C2=A0 #define kernel_mapping_va_to_pa(x)=C2=A0=C2=A0=C2=A0 ((u= nsigned long)(x) -=20 >>> va_kernel_pa_offset) >>> +#endif >>> =C2=A0=C2=A0 #define __va_to_pa_nodebug(x)=C2=A0=C2=A0=C2=A0 ({=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 unsigned long _x =3D x;=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0 \ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (_x < kernel_virt_addr) ?=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \ >>> @@ -139,9 +160,16 @@ extern phys_addr_t __phys_addr_symbol(unsigned=20 >>> long x); >>> =C2=A0=C2=A0 #define phys_to_page(paddr)=C2=A0=C2=A0=C2=A0 (pfn_to_pa= ge(phys_to_pfn(paddr))) >>> =C2=A0=C2=A0 #ifdef CONFIG_FLATMEM >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define pfn_valid(pfn) \ >>> +=C2=A0=C2=A0=C2=A0 ((((pfn) >=3D ARCH_PFN_OFFSET) && (((pfn) - ARCH_= PFN_OFFSET) <=20 >>> max_mapnr)) ||=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ((pfn) >=3D PFN_DOWN(CONF= IG_XIP_PHYS_ADDR) &&=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (((pfn) - PFN_DOWN(CONFIG= _XIP_PHYS_ADDR)) < XIP_OFFSET))) >>> +#else >>> =C2=A0=C2=A0 #define pfn_valid(pfn) \ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (((pfn) >=3D ARCH_PFN_OFFSET) &&= (((pfn) - ARCH_PFN_OFFSET) <=20 >>> max_mapnr)) >>> =C2=A0=C2=A0 #endif >>> +#endif >>> =C2=A0=C2=A0 #endif /* __ASSEMBLY__ */ >>> diff --git a/arch/riscv/include/asm/pgtable.h=20 >>> b/arch/riscv/include/asm/pgtable.h >>> index 80e63a93e903..c2dc4f83eed8 100644 >>> --- a/arch/riscv/include/asm/pgtable.h >>> +++ b/arch/riscv/include/asm/pgtable.h >>> @@ -64,6 +64,19 @@ >>> =C2=A0=C2=A0 #define FIXADDR_SIZE=C2=A0=C2=A0=C2=A0=C2=A0 PGDIR_SIZE >>> =C2=A0=C2=A0 #endif >>> =C2=A0=C2=A0 #define FIXADDR_START=C2=A0=C2=A0=C2=A0 (FIXADDR_TOP - F= IXADDR_SIZE) >>> + >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define XIP_OFFSET=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 SZ_8M >>> +#define XIP_FIXUP(addr) ({=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0 uintptr_t __a =3D (uintptr_t)(addr);=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0 (__a >=3D CONFIG_XIP_PHYS_ADDR && __a < CONFIG_XI= P_PHYS_ADDR +=20 >>> SZ_16M) ?=C2=A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __a - CONFIG_XIP_PHYS_ADD= R + CONFIG_PHYS_RAM_BASE -=20 >>> XIP_OFFSET :\ >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __a;=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0 \ >>> +=C2=A0=C2=A0=C2=A0 }) >>> +#else >>> +#define XIP_FIXUP(addr)=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (a= ddr) >>> +#endif /* CONFIG_XIP_KERNEL */ >>> + >>> =C2=A0=C2=A0 #endif >>> =C2=A0=C2=A0 #ifndef __ASSEMBLY__ >>> @@ -499,8 +512,16 @@ static inline int ptep_clear_flush_young(struct=20 >>> vm_area_struct *vma, >>> =C2=A0=C2=A0 #define kern_addr_valid(addr)=C2=A0=C2=A0 (1) /* FIXME *= / >>> =C2=A0=C2=A0 extern char _start[]; >>> -extern void *dtb_early_va; >>> -extern uintptr_t dtb_early_pa; >>> +extern void *_dtb_early_va; >>> +extern uintptr_t _dtb_early_pa; >>> +#if defined(CONFIG_XIP_KERNEL) && defined(CONFIG_MMU) >>> +#define dtb_early_va=C2=A0=C2=A0=C2=A0 (*(void **)XIP_FIXUP(&_dtb_ea= rly_va)) >>> +#define dtb_early_pa=C2=A0=C2=A0=C2=A0 (*(uintptr_t *)XIP_FIXUP(&_dt= b_early_pa)) >>> +#else >>> +#define dtb_early_va=C2=A0=C2=A0=C2=A0 _dtb_early_va >>> +#define dtb_early_pa=C2=A0=C2=A0=C2=A0 _dtb_early_pa >>> +#endif /* CONFIG_XIP_KERNEL */ >>> + >>> =C2=A0=C2=A0 void setup_bootmem(void); >>> =C2=A0=C2=A0 void paging_init(void); >>> =C2=A0=C2=A0 void misc_mem_init(void); >>> diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S >>> index 6cb05f22e52a..89cc58ab52b4 100644 >>> --- a/arch/riscv/kernel/head.S >>> +++ b/arch/riscv/kernel/head.S >>> @@ -9,11 +9,23 @@ >>> =C2=A0=C2=A0 #include >>> =C2=A0=C2=A0 #include >>> =C2=A0=C2=A0 #include >>> +#include >>> =C2=A0=C2=A0 #include >>> =C2=A0=C2=A0 #include >>> =C2=A0=C2=A0 #include >>> =C2=A0=C2=A0 #include "efi-header.S" >>> +#ifdef CONFIG_XIP_KERNEL >>> +.macro XIP_FIXUP_OFFSET reg >>> +=C2=A0=C2=A0=C2=A0 REG_L t0, _xip_fixup >>> +=C2=A0=C2=A0=C2=A0 add \reg, \reg, t0 >>> +.endm >>> +_xip_fixup: .dword CONFIG_PHYS_RAM_BASE - CONFIG_XIP_PHYS_ADDR -=20 >>> XIP_OFFSET >>> +#else >>> +.macro XIP_FIXUP_OFFSET reg >>> +.endm >>> +#endif /* CONFIG_XIP_KERNEL */ >>> + >>> =C2=A0=C2=A0 __HEAD >>> =C2=A0=C2=A0 ENTRY(_start) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* >>> @@ -70,6 +82,7 @@ pe_head_start: >>> =C2=A0=C2=A0 relocate: >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Relocate return address */ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a1, kernel_virt_addr >>> +=C2=A0=C2=A0=C2=A0 XIP_FIXUP_OFFSET a1 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 REG_L a1, 0(a1) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a2, _start >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 sub a1, a1, a2 >>> @@ -92,6 +105,7 @@ relocate: >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * to ensure the new transl= ations are in use. >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 */ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a0, trampoline_pg_dir >>> +=C2=A0=C2=A0=C2=A0 XIP_FIXUP_OFFSET a0 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 srl a0, a0, PAGE_SHIFT >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 or a0, a0, a1 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 sfence.vma >>> @@ -145,7 +159,9 @@ secondary_start_sbi: >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 slli a3, a0, LGREG >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a4, __cpu_up_stack_pointer >>> +=C2=A0=C2=A0=C2=A0 XIP_FIXUP_OFFSET a4 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a5, __cpu_up_task_pointer >>> +=C2=A0=C2=A0=C2=A0 XIP_FIXUP_OFFSET a5 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 add a4, a3, a4 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 add a5, a3, a5 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 REG_L sp, (a4) >>> @@ -157,6 +173,7 @@ secondary_start_common: >>> =C2=A0=C2=A0 #ifdef CONFIG_MMU >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Enable virtual memory and rel= ocate to virtual address */ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a0, swapper_pg_dir >>> +=C2=A0=C2=A0=C2=A0 XIP_FIXUP_OFFSET a0 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 call relocate >>> =C2=A0=C2=A0 #endif >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 call setup_trap_vector >>> @@ -237,12 +254,33 @@ pmp_done: >>> =C2=A0=C2=A0 .Lgood_cores: >>> =C2=A0=C2=A0 #endif >>> +#ifndef CONFIG_XIP_KERNEL >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Pick one hart to run the main= boot sequence */ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a3, hart_lottery >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 li a2, 1 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 amoadd.w a3, a2, (a3) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 bnez a3, .Lsecondary_start >>> +#else >>> +=C2=A0=C2=A0=C2=A0 /* hart_lottery in flash contains a magic number = */ >>> +=C2=A0=C2=A0=C2=A0 la a3, hart_lottery >>> +=C2=A0=C2=A0=C2=A0 mv a2, a3 >>> +=C2=A0=C2=A0=C2=A0 XIP_FIXUP_OFFSET a2 >>> +=C2=A0=C2=A0=C2=A0 lw t1, (a3) >>> +=C2=A0=C2=A0=C2=A0 amoswap.w t0, t1, (a2) >>> +=C2=A0=C2=A0=C2=A0 /* first time here if hart_lottery in RAM is not = set */ >>> +=C2=A0=C2=A0=C2=A0 beq t0, t1, .Lsecondary_start >>> + >>> +=C2=A0=C2=A0=C2=A0 la sp, _end + THREAD_SIZE >>> +=C2=A0=C2=A0=C2=A0 XIP_FIXUP_OFFSET sp >>> +=C2=A0=C2=A0=C2=A0 mv s0, a0 >>> +=C2=A0=C2=A0=C2=A0 call __copy_data >>> + >>> +=C2=A0=C2=A0=C2=A0 /* Restore a0 copy */ >>> +=C2=A0=C2=A0=C2=A0 mv a0, s0 >>> +#endif >>> + >>> +#ifndef CONFIG_XIP_KERNEL >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Clear BSS for flat non-ELF im= ages */ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a3, __bss_start >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a4, __bss_stop >>> @@ -252,15 +290,18 @@ clear_bss: >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 add a3, a3, RISCV_SZPTR >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 blt a3, a4, clear_bss >>> =C2=A0=C2=A0 clear_bss_done: >>> - >>> +#endif >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Save hart ID and DTB physical= address */ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 mv s0, a0 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 mv s1, a1 >>> + >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a2, boot_cpu_hartid >>> +=C2=A0=C2=A0=C2=A0 XIP_FIXUP_OFFSET a2 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 REG_S a0, (a2) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Initialize page tables and re= locate to virtual addresses */ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la sp, init_thread_union + THREA= D_SIZE >>> +=C2=A0=C2=A0=C2=A0 XIP_FIXUP_OFFSET sp >>> =C2=A0=C2=A0 #ifdef CONFIG_BUILTIN_DTB >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a0, __dtb_start >>> =C2=A0=C2=A0 #else >>> @@ -269,6 +310,7 @@ clear_bss_done: >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 call setup_vm >>> =C2=A0=C2=A0 #ifdef CONFIG_MMU >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a0, early_pg_dir >>> +=C2=A0=C2=A0=C2=A0 XIP_FIXUP_OFFSET a0 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 call relocate >>> =C2=A0=C2=A0 #endif /* CONFIG_MMU */ >>> @@ -293,7 +335,9 @@ clear_bss_done: >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 slli a3, a0, LGREG >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a1, __cpu_up_stack_pointer >>> +=C2=A0=C2=A0=C2=A0 XIP_FIXUP_OFFSET a1 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la a2, __cpu_up_task_pointer >>> +=C2=A0=C2=A0=C2=A0 XIP_FIXUP_OFFSET a2 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 add a1, a3, a1 >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 add a2, a3, a2 >>> diff --git a/arch/riscv/kernel/head.h b/arch/riscv/kernel/head.h >>> index b48dda3d04f6..aabbc3ac3e48 100644 >>> --- a/arch/riscv/kernel/head.h >>> +++ b/arch/riscv/kernel/head.h >>> @@ -12,6 +12,9 @@ extern atomic_t hart_lottery; >>> =C2=A0=C2=A0 asmlinkage void do_page_fault(struct pt_regs *regs); >>> =C2=A0=C2=A0 asmlinkage void __init setup_vm(uintptr_t dtb_pa); >>> +#ifdef CONFIG_XIP_KERNEL >>> +asmlinkage void __init __copy_data(void); >>> +#endif >>> =C2=A0=C2=A0 extern void *__cpu_up_stack_pointer[]; >>> =C2=A0=C2=A0 extern void *__cpu_up_task_pointer[]; >>> diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c >>> index 30e4af0fd50c..2ddf654c72bb 100644 >>> --- a/arch/riscv/kernel/setup.c >>> +++ b/arch/riscv/kernel/setup.c >>> @@ -50,7 +50,11 @@ struct screen_info screen_info __section(".data") = =3D { >>> =C2=A0=C2=A0=C2=A0 * This is used before the kernel initializes the B= SS so it can't=20 >>> be in the >>> =C2=A0=C2=A0=C2=A0 * BSS. >>> =C2=A0=C2=A0=C2=A0 */ >>> -atomic_t hart_lottery __section(".sdata"); >>> +atomic_t hart_lottery __section(".sdata") >>> +#ifdef CONFIG_XIP_KERNEL >>> +=3D ATOMIC_INIT(0xC001BEEF) >>> +#endif >>> +; >>> =C2=A0=C2=A0 unsigned long boot_cpu_hartid; >>> =C2=A0=C2=A0 static DEFINE_PER_CPU(struct cpu, cpu_devices); >>> @@ -254,7 +258,7 @@ void __init setup_arch(char **cmdline_p) >>> =C2=A0=C2=A0 #if IS_ENABLED(CONFIG_BUILTIN_DTB) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 unflatten_and_copy_device_tree()= ; >>> =C2=A0=C2=A0 #else >>> -=C2=A0=C2=A0=C2=A0 if (early_init_dt_verify(__va(dtb_early_pa))) >>> +=C2=A0=C2=A0=C2=A0 if (early_init_dt_verify(__va(XIP_FIXUP(dtb_early= _pa)))) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 unflatte= n_device_tree(); >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 else >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pr_err("= No DTB found in kernel mappings\n"); >>> @@ -266,7 +270,7 @@ void __init setup_arch(char **cmdline_p) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (IS_ENABLED(CONFIG_STRICT_KER= NEL_RWX)) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 protect_= kernel_text_data(); >>> -#if defined(CONFIG_64BIT) && defined(CONFIG_MMU) >>> +#if defined(CONFIG_64BIT) && defined(CONFIG_MMU) &&=20 >>> !defined(CONFIG_XIP_KERNEL) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 protect_kernel_linear_mapping_te= xt_rodata(); >>> =C2=A0=C2=A0 #endif >>> diff --git a/arch/riscv/kernel/vmlinux-xip.lds.S=20 >>> b/arch/riscv/kernel/vmlinux-xip.lds.S >>> new file mode 100644 >>> index 000000000000..4b29b9917f99 >>> --- /dev/null >>> +++ b/arch/riscv/kernel/vmlinux-xip.lds.S >>> @@ -0,0 +1,133 @@ >>> +/* SPDX-License-Identifier: GPL-2.0-only */ >>> +/* >>> + * Copyright (C) 2012 Regents of the University of California >>> + * Copyright (C) 2017 SiFive >>> + * Copyright (C) 2020 Vitaly Wool, Konsulko AB >>> + */ >>> + >>> +#include >>> +#define LOAD_OFFSET KERNEL_LINK_ADDR >>> +/* No __ro_after_init data in the .rodata section - which will=20 >>> always be ro */ >>> +#define RO_AFTER_INIT_DATA >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +OUTPUT_ARCH(riscv) >>> +ENTRY(_start) >>> + >>> +jiffies =3D jiffies_64; >>> + >>> +SECTIONS >>> +{ >>> +=C2=A0=C2=A0=C2=A0 /* Beginning of code and text segment */ >>> +=C2=A0=C2=A0=C2=A0 . =3D LOAD_OFFSET; >>> +=C2=A0=C2=A0=C2=A0 _xiprom =3D .; >>> +=C2=A0=C2=A0=C2=A0 _start =3D .; >>> +=C2=A0=C2=A0=C2=A0 HEAD_TEXT_SECTION >>> +=C2=A0=C2=A0=C2=A0 INIT_TEXT_SECTION(PAGE_SIZE) >>> +=C2=A0=C2=A0=C2=A0 /* we have to discard exit text and such at runti= me, not link=20 >>> time */ >>> +=C2=A0=C2=A0=C2=A0 .exit.text : >>> +=C2=A0=C2=A0=C2=A0 { >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 EXIT_TEXT >>> +=C2=A0=C2=A0=C2=A0 } >>> + >>> +=C2=A0=C2=A0=C2=A0 .text : { >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 _text =3D .; >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 _stext =3D .; >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 TEXT_TEXT >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 SCHED_TEXT >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 CPUIDLE_TEXT >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 LOCK_TEXT >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 KPROBES_TEXT >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ENTRY_TEXT >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 IRQENTRY_TEXT >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 SOFTIRQENTRY_TEXT >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 *(.fixup) >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 _etext =3D .; >>> +=C2=A0=C2=A0=C2=A0 } >>> +=C2=A0=C2=A0=C2=A0 RO_DATA(L1_CACHE_BYTES) >>> +=C2=A0=C2=A0=C2=A0 .srodata : { >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 *(.srodata*) >>> +=C2=A0=C2=A0=C2=A0 } >>> +=C2=A0=C2=A0=C2=A0 .init.rodata : { >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 INIT_SETUP(16) >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 INIT_CALLS >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 CON_INITCALL >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 INIT_RAM_FS >>> +=C2=A0=C2=A0=C2=A0 } >>> +=C2=A0=C2=A0=C2=A0 _exiprom =3D .;=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* End of XIP ROM area */ >>> + >>> + >>> +/* >>> + * From this point, stuff is considered writable and will be copied=20 >>> to RAM >>> + */ >>> +=C2=A0=C2=A0=C2=A0 __data_loc =3D ALIGN(16);=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0 /* location in file */ >>> +=C2=A0=C2=A0=C2=A0 . =3D LOAD_OFFSET + XIP_OFFSET;=C2=A0=C2=A0=C2=A0= /* location in memory */ >>> + >>> +=C2=A0=C2=A0=C2=A0 _sdata =3D .;=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Start of data section */ >>> +=C2=A0=C2=A0=C2=A0 _data =3D .; >>> +=C2=A0=C2=A0=C2=A0 RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) >>> +=C2=A0=C2=A0=C2=A0 _edata =3D .; >>> +=C2=A0=C2=A0=C2=A0 __start_ro_after_init =3D .; >>> +=C2=A0=C2=A0=C2=A0 .data.ro_after_init : AT(ADDR(.data.ro_after_init= ) - LOAD_OFFSET) { >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 *(.data..ro_after_init) >>> +=C2=A0=C2=A0=C2=A0 } >>> +=C2=A0=C2=A0=C2=A0 __end_ro_after_init =3D .; >>> + >>> +=C2=A0=C2=A0=C2=A0 . =3D ALIGN(PAGE_SIZE); >>> +=C2=A0=C2=A0=C2=A0 __init_begin =3D .; >>> +=C2=A0=C2=A0=C2=A0 .init.data : { >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 INIT_DATA >>> +=C2=A0=C2=A0=C2=A0 } >>> +=C2=A0=C2=A0=C2=A0 .exit.data : { >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 EXIT_DATA >>> +=C2=A0=C2=A0=C2=A0 } >>> +=C2=A0=C2=A0=C2=A0 . =3D ALIGN(8); >>> +=C2=A0=C2=A0=C2=A0 __soc_early_init_table : { >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __soc_early_init_table_st= art =3D .; >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 KEEP(*(__soc_early_init_t= able)) >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __soc_early_init_table_en= d =3D .; >>> +=C2=A0=C2=A0=C2=A0 } >>> +=C2=A0=C2=A0=C2=A0 __soc_builtin_dtb_table : { >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __soc_builtin_dtb_table_s= tart =3D .; >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 KEEP(*(__soc_builtin_dtb_= table)) >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __soc_builtin_dtb_table_e= nd =3D .; >>> +=C2=A0=C2=A0=C2=A0 } >>> +=C2=A0=C2=A0=C2=A0 PERCPU_SECTION(L1_CACHE_BYTES) >>> + >>> +=C2=A0=C2=A0=C2=A0 . =3D ALIGN(PAGE_SIZE); >>> +=C2=A0=C2=A0=C2=A0 __init_end =3D .; >>> + >>> +=C2=A0=C2=A0=C2=A0 .sdata : { >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __global_pointer$ =3D . += 0x800; >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 *(.sdata*) >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 *(.sbss*) >>> +=C2=A0=C2=A0=C2=A0 } >>> + >>> +=C2=A0=C2=A0=C2=A0 BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0) >>> +=C2=A0=C2=A0=C2=A0 EXCEPTION_TABLE(0x10) >>> + >>> +=C2=A0=C2=A0=C2=A0 .rel.dyn : AT(ADDR(.rel.dyn) - LOAD_OFFSET) { >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 *(.rel.dyn*) >>> +=C2=A0=C2=A0=C2=A0 } >>> + >>> +=C2=A0=C2=A0=C2=A0 /* >>> +=C2=A0=C2=A0=C2=A0=C2=A0 * End of copied data. We need a dummy secti= on to get its LMA. >>> +=C2=A0=C2=A0=C2=A0=C2=A0 * Also located before final ALIGN() as trai= ling padding is not=20 >>> stored >>> +=C2=A0=C2=A0=C2=A0=C2=A0 * in the resulting binary file and useless = to copy. >>> +=C2=A0=C2=A0=C2=A0=C2=A0 */ >>> +=C2=A0=C2=A0=C2=A0 .data.endmark : AT(ADDR(.data.endmark) - LOAD_OFF= SET) { } >>> +=C2=A0=C2=A0=C2=A0 _edata_loc =3D LOADADDR(.data.endmark); >>> + >>> +=C2=A0=C2=A0=C2=A0 . =3D ALIGN(PAGE_SIZE); >>> +=C2=A0=C2=A0=C2=A0 _end =3D .; >>> + >>> +=C2=A0=C2=A0=C2=A0 STABS_DEBUG >>> +=C2=A0=C2=A0=C2=A0 DWARF_DEBUG >>> + >>> +=C2=A0=C2=A0=C2=A0 DISCARDS >>> +} >>> diff --git a/arch/riscv/kernel/vmlinux.lds.S=20 >>> b/arch/riscv/kernel/vmlinux.lds.S >>> index 0726c05e0336..0a59b65cf789 100644 >>> --- a/arch/riscv/kernel/vmlinux.lds.S >>> +++ b/arch/riscv/kernel/vmlinux.lds.S >>> @@ -4,8 +4,13 @@ >>> =C2=A0=C2=A0=C2=A0 * Copyright (C) 2017 SiFive >>> =C2=A0=C2=A0=C2=A0 */ >>> +#ifdef CONFIG_XIP_KERNEL >>> +#include "vmlinux-xip.lds.S" >>> +#else >>> + >>> =C2=A0=C2=A0 #include >>> =C2=A0=C2=A0 #define LOAD_OFFSET KERNEL_LINK_ADDR >>> + >>> =C2=A0=C2=A0 #include >>> =C2=A0=C2=A0 #include >>> =C2=A0=C2=A0 #include >>> @@ -133,3 +138,4 @@ SECTIONS >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 DISCARDS >>> =C2=A0=C2=A0 } >>> +#endif /* CONFIG_XIP_KERNEL */ >>> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c >>> index 093f3a96ecfc..9961573f9a55 100644 >>> --- a/arch/riscv/mm/init.c >>> +++ b/arch/riscv/mm/init.c >>> @@ -27,6 +27,9 @@ >>> =C2=A0=C2=A0 unsigned long kernel_virt_addr =3D KERNEL_LINK_ADDR; >>> =C2=A0=C2=A0 EXPORT_SYMBOL(kernel_virt_addr); >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define kernel_virt_addr=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (*((uns= igned long=20 >>> *)XIP_FIXUP(&kernel_virt_addr))) >>> +#endif >>> =C2=A0=C2=A0 unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigne= d long)] >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __page_aligned_bss; >>> @@ -34,8 +37,8 @@ EXPORT_SYMBOL(empty_zero_page); >>> =C2=A0=C2=A0 extern char _start[]; >>> =C2=A0=C2=A0 #define DTB_EARLY_BASE_VA=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 = PGDIR_SIZE >>> -void *dtb_early_va __initdata; >>> -uintptr_t dtb_early_pa __initdata; >>> +void *_dtb_early_va __initdata; >>> +uintptr_t _dtb_early_pa __initdata; >>> =C2=A0=C2=A0 struct pt_alloc_ops { >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pte_t *(*get_pte_virt)(phys_addr= _t pa); >>> @@ -118,6 +121,10 @@ void __init setup_bootmem(void) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 phys_addr_t dram_end =3D membloc= k_end_of_DRAM(); >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 phys_addr_t max_mapped_addr =3D = __pa(~(ulong)0); >>> +#ifdef CONFIG_XIP_KERNEL >>> +=C2=A0=C2=A0=C2=A0 vmlinux_start =3D __pa_symbol(&_sdata); >>> +#endif >>> + >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* The maximal physical memory s= ize is -PAGE_OFFSET. */ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 memblock_enforce_memory_limit(-P= AGE_OFFSET); >>> @@ -159,17 +166,44 @@ void __init setup_bootmem(void) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 memblock_allow_resize(); >>> =C2=A0=C2=A0 } >>> +#ifdef CONFIG_XIP_KERNEL >>> + >>> +extern char _xiprom[], _exiprom[]; >>> +extern char _sdata[], _edata[]; >>> + >>> +#endif /* CONFIG_XIP_KERNEL */ >>> + >>> =C2=A0=C2=A0 #ifdef CONFIG_MMU >>> -static struct pt_alloc_ops pt_ops; >>> +static struct pt_alloc_ops _pt_ops; >>> + >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define pt_ops (*(struct pt_alloc_ops *)XIP_FIXUP(&_pt_ops)) >>> +#else >>> +#define pt_ops _pt_ops >>> +#endif >>> =C2=A0=C2=A0 /* Offset between linear mapping virtual address and ker= nel load=20 >>> address */ >>> =C2=A0=C2=A0 unsigned long va_pa_offset; >>> =C2=A0=C2=A0 EXPORT_SYMBOL(va_pa_offset); >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define va_pa_offset=C2=A0=C2=A0 (*((unsigned long *)XIP_FIXUP(&va_p= a_offset))) >>> +#endif >>> =C2=A0=C2=A0 /* Offset between kernel mapping virtual address and ker= nel load=20 >>> address */ >>> =C2=A0=C2=A0 unsigned long va_kernel_pa_offset; >>> =C2=A0=C2=A0 EXPORT_SYMBOL(va_kernel_pa_offset); >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define va_kernel_pa_offset=C2=A0=C2=A0=C2=A0 (*((unsigned long=20 >>> *)XIP_FIXUP(&va_kernel_pa_offset))) >>> +#endif >>> +unsigned long va_kernel_xip_pa_offset; >>> +EXPORT_SYMBOL(va_kernel_xip_pa_offset); >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define va_kernel_xip_pa_offset=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0 (*((unsigned long=20 >>> *)XIP_FIXUP(&va_kernel_xip_pa_offset))) >>> +#endif >>> =C2=A0=C2=A0 unsigned long pfn_base; >>> =C2=A0=C2=A0 EXPORT_SYMBOL(pfn_base); >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define pfn_base=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (*((unsigned lo= ng *)XIP_FIXUP(&pfn_base))) >>> +#endif >>> =C2=A0=C2=A0 pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss; >>> =C2=A0=C2=A0 pgd_t trampoline_pg_dir[PTRS_PER_PGD] __page_aligned_bss= ; >>> @@ -177,6 +211,12 @@ pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bs= s; >>> =C2=A0=C2=A0 pgd_t early_pg_dir[PTRS_PER_PGD] __initdata __aligned(PA= GE_SIZE); >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define trampoline_pg_dir=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ((pgd_t *)XI= P_FIXUP(trampoline_pg_dir)) >>> +#define fixmap_pte=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0 ((pte_t *)XIP_FIXUP(fixmap_pte)) >>> +#define early_pg_dir=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0 ((pgd_t *)XIP_FIXUP(early_pg_dir)) >>> +#endif /* CONFIG_XIP_KERNEL */ >>> + >>> =C2=A0=C2=A0 void __set_fixmap(enum fixed_addresses idx, phys_addr_t = phys,=20 >>> pgprot_t prot) >>> =C2=A0=C2=A0 { >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 unsigned long addr =3D __fix_to_= virt(idx); >>> @@ -252,6 +292,12 @@ pmd_t fixmap_pmd[PTRS_PER_PMD] __page_aligned_bs= s; >>> =C2=A0=C2=A0 pmd_t early_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_= SIZE); >>> =C2=A0=C2=A0 pmd_t early_dtb_pmd[PTRS_PER_PMD] __initdata __aligned(P= AGE_SIZE); >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define trampoline_pmd ((pmd_t *)XIP_FIXUP(trampoline_pmd)) >>> +#define fixmap_pmd=C2=A0=C2=A0=C2=A0=C2=A0 ((pmd_t *)XIP_FIXUP(fixma= p_pmd)) >>> +#define early_pmd=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ((pmd_t *)XIP_FIXUP(= early_pmd)) >>> +#endif /* CONFIG_XIP_KERNEL */ >>> + >>> =C2=A0=C2=A0 static pmd_t *__init get_pmd_virt_early(phys_addr_t pa) >>> =C2=A0=C2=A0 { >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Before MMU is enabled */ >>> @@ -368,6 +414,19 @@ static uintptr_t __init=20 >>> best_map_size(phys_addr_t base, phys_addr_t size) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return PMD_SIZE; >>> =C2=A0=C2=A0 } >>> +#ifdef CONFIG_XIP_KERNEL >>> +/* called from head.S with MMU off */ >>> +asmlinkage void __init __copy_data(void) >>> +{ >>> +=C2=A0=C2=A0=C2=A0 void *from =3D (void *)(&_sdata); >>> +=C2=A0=C2=A0=C2=A0 void *end =3D (void *)(&_end); >>> +=C2=A0=C2=A0=C2=A0 void *to =3D (void *)CONFIG_PHYS_RAM_BASE; >>> +=C2=A0=C2=A0=C2=A0 size_t sz =3D (size_t)(end - from + 1); >>> + >>> +=C2=A0=C2=A0=C2=A0 memcpy(to, from, sz); >>> +} >>> +#endif >>> + >>> =C2=A0=C2=A0 /* >>> =C2=A0=C2=A0=C2=A0 * setup_vm() is called from head.S with MMU-off. >>> =C2=A0=C2=A0=C2=A0 * >>> @@ -387,7 +446,35 @@ static uintptr_t __init=20 >>> best_map_size(phys_addr_t base, phys_addr_t size) >>> =C2=A0=C2=A0 #endif >>> =C2=A0=C2=A0 uintptr_t load_pa, load_sz; >>> +#ifdef CONFIG_XIP_KERNEL >>> +#define load_pa=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (*((uintpt= r_t *)XIP_FIXUP(&load_pa))) >>> +#define load_sz=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (*((uintpt= r_t *)XIP_FIXUP(&load_sz))) >>> +#endif >>> + >>> +#ifdef CONFIG_XIP_KERNEL >>> +uintptr_t xiprom, xiprom_sz; >>> +#define xiprom_sz=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (*((uintptr_t *)XIP_= FIXUP(&xiprom_sz))) >>> +#define xiprom=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (*((u= intptr_t *)XIP_FIXUP(&xiprom))) >>> +static void __init create_kernel_page_table(pgd_t *pgdir, uintptr_t=20 >>> map_size) >>> +{ >>> +=C2=A0=C2=A0=C2=A0 uintptr_t va, end_va; >>> + >>> +=C2=A0=C2=A0=C2=A0 /* Map the flash resident part */ >>> +=C2=A0=C2=A0=C2=A0 end_va =3D kernel_virt_addr + xiprom_sz; >>> +=C2=A0=C2=A0=C2=A0 for (va =3D kernel_virt_addr; va < end_va; va +=3D= map_size) >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 create_pgd_mapping(pgdir,= va, >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 xiprom + (va - kernel_virt_addr), >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 map_size, PAGE_KERNEL_EXEC); >>> + >>> +=C2=A0=C2=A0=C2=A0 /* Map the data in RAM */ >>> +=C2=A0=C2=A0=C2=A0 end_va =3D kernel_virt_addr + XIP_OFFSET + load_s= z; >>> +=C2=A0=C2=A0=C2=A0 for (va =3D kernel_virt_addr + XIP_OFFSET; va < e= nd_va; va +=3D=20 >>> map_size) >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 create_pgd_mapping(pgdir,= va, >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 load_pa + (va - (kernel_virt_addr= + XIP_OFFSET)), >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 map_size, PAGE_KERNEL); >>> +} >>> +#else >>> =C2=A0=C2=A0 static void __init create_kernel_page_table(pgd_t *pgdir= ,=20 >>> uintptr_t map_size) >>> =C2=A0=C2=A0 { >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 uintptr_t va, end_va; >>> @@ -398,16 +485,28 @@ static void __init=20 >>> create_kernel_page_table(pgd_t *pgdir, uintptr_t map_size) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 load_pa + (va -= kernel_virt_addr), >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 map_size, PAGE_= KERNEL_EXEC); >>> =C2=A0=C2=A0 } >>> +#endif >>> =C2=A0=C2=A0 asmlinkage void __init setup_vm(uintptr_t dtb_pa) >>> =C2=A0=C2=A0 { >>> -=C2=A0=C2=A0=C2=A0 uintptr_t pa; >>> +=C2=A0=C2=A0=C2=A0 uintptr_t __maybe_unused pa; >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 uintptr_t map_size; >>> =C2=A0=C2=A0 #ifndef __PAGETABLE_PMD_FOLDED >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pmd_t fix_bmap_spmd, fix_bmap_ep= md; >>> =C2=A0=C2=A0 #endif >>> + >>> +#ifdef CONFIG_XIP_KERNEL >>> +=C2=A0=C2=A0=C2=A0 xiprom =3D (uintptr_t)CONFIG_XIP_PHYS_ADDR; >>> +=C2=A0=C2=A0=C2=A0 xiprom_sz =3D (uintptr_t)(&_exiprom) - (uintptr_t= )(&_xiprom); >>> + >>> +=C2=A0=C2=A0=C2=A0 load_pa =3D (uintptr_t)CONFIG_PHYS_RAM_BASE; >>> +=C2=A0=C2=A0=C2=A0 load_sz =3D (uintptr_t)(&_end) - (uintptr_t)(&_sd= ata); >>> + >>> +=C2=A0=C2=A0=C2=A0 va_kernel_xip_pa_offset =3D kernel_virt_addr - xi= prom; >>> +#else >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 load_pa =3D (uintptr_t)(&_start)= ; >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 load_sz =3D (uintptr_t)(&_end) -= load_pa; >>> +#endif >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 va_pa_offset =3D PAGE_OFFSET - l= oad_pa; >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 va_kernel_pa_offset =3D kernel_v= irt_addr - load_pa; >>> @@ -441,8 +540,13 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa= ) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Setup trampoline PGD and PMD = */ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 create_pgd_mapping(trampoline_pg= _dir, kernel_virt_addr, >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (uintptr_t)trampoline_pmd, PGDIR_SIZE, = PAGE_TABLE); >>> +#ifdef CONFIG_XIP_KERNEL >>> +=C2=A0=C2=A0=C2=A0 create_pmd_mapping(trampoline_pmd, kernel_virt_ad= dr, >>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0 xiprom, PMD_SIZE, PAGE_KERNEL_EXEC); >>> +#else >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 create_pmd_mapping(trampoline_pm= d, kernel_virt_addr, >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 load_pa, PMD_SIZE, PAGE_KERNEL_EXEC); >>> +#endif >>> =C2=A0=C2=A0 #else >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Setup trampoline PGD */ >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 create_pgd_mapping(trampoline_pg= _dir, kernel_virt_addr, >>> @@ -474,7 +578,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * whereas dtb_early_va wil= l be used before setup_vm_final=20 >>> installs >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * the linear mapping. >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 */ >>> -=C2=A0=C2=A0=C2=A0 dtb_early_va =3D kernel_mapping_pa_to_va(dtb_pa); >>> +=C2=A0=C2=A0=C2=A0 dtb_early_va =3D kernel_mapping_pa_to_va(XIP_FIXU= P(dtb_pa)); >>> =C2=A0=C2=A0 #endif /* CONFIG_BUILTIN_DTB */ >>> =C2=A0=C2=A0 #else >>> =C2=A0=C2=A0 #ifndef CONFIG_BUILTIN_DTB >>> @@ -486,7 +590,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pa + PGDIR_SIZE, PGDIR_SIZE, PAGE_KERNE= L); >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 dtb_early_va =3D (void *)DTB_EAR= LY_BASE_VA + (dtb_pa &=20 >>> (PGDIR_SIZE - 1)); >>> =C2=A0=C2=A0 #else /* CONFIG_BUILTIN_DTB */ >>> -=C2=A0=C2=A0=C2=A0 dtb_early_va =3D kernel_mapping_pa_to_va(dtb_pa); >>> +=C2=A0=C2=A0=C2=A0 dtb_early_va =3D kernel_mapping_pa_to_va(XIP_FIXU= P(dtb_pa)); >>> =C2=A0=C2=A0 #endif /* CONFIG_BUILTIN_DTB */ >>> =C2=A0=C2=A0 #endif >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 dtb_early_pa =3D dtb_pa; >>> @@ -522,7 +626,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) >>> =C2=A0=C2=A0 #endif >>> =C2=A0=C2=A0 } >>> -#ifdef CONFIG_64BIT >>> +#if defined(CONFIG_64BIT) && !defined(CONFIG_XIP_KERNEL) >>> =C2=A0=C2=A0 void protect_kernel_linear_mapping_text_rodata(void) >>> =C2=A0=C2=A0 { >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 unsigned long text_start =3D (un= signed long)lm_alias(_start); >>> >> >=20 >=20