Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xtensa: add XIP kernel support

XIP (eXecute In Place) kernel image is the image that can be run
directly from ROM, using RAM only for writable data.

XIP xtensa kernel differs from regular xtensa kernel in the following
ways:
- it has exception/IRQ vectors merged into text section. No vectors
relocation takes place at kernel startup.
- .data/.bss location must be specified in the kernel configuration,
its content is copied there in the _startup function.
- .init.text is merged with the rest of text and is executed from ROM.
- when MMU is used the virtual address where the kernel will be mapped
must be specified in the kernel configuration. It may be in the KSEG
or in the KIO, __pa macro is adjusted to be able to handle both.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>

+257 -5
+46 -2
arch/xtensa/Kconfig
··· 19 19 select GENERIC_PCI_IOMAP 20 20 select GENERIC_SCHED_CLOCK 21 21 select GENERIC_STRNCPY_FROM_USER if KASAN 22 - select HAVE_ARCH_JUMP_LABEL 23 - select HAVE_ARCH_KASAN if MMU 22 + select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL 23 + select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL 24 24 select HAVE_ARCH_TRACEHOOK 25 25 select HAVE_DEBUG_KMEMLEAK 26 26 select HAVE_DMA_CONTIGUOUS ··· 299 299 config SERIAL_CONSOLE 300 300 def_bool n 301 301 302 + config PLATFORM_HAVE_XIP 303 + def_bool n 304 + 302 305 menu "Platform options" 303 306 304 307 choice ··· 328 325 select PLATFORM_WANT_DEFAULT_MEM if !MMU 329 326 select SERIAL_CONSOLE 330 327 select XTENSA_CALIBRATE_CCOUNT 328 + select PLATFORM_HAVE_XIP 331 329 help 332 330 XTFPGA is the name of Tensilica board family (LX60, LX110, LX200, ML605). 333 331 This hardware is capable of running a full Linux distribution. ··· 482 478 483 479 If in doubt, say Y. 484 480 481 + config XIP_KERNEL 482 + bool "Kernel Execute-In-Place from ROM" 483 + depends on PLATFORM_HAVE_XIP 484 + help 485 + Execute-In-Place allows the kernel to run from non-volatile storage 486 + directly addressable by the CPU, such as NOR flash. This saves RAM 487 + space since the text section of the kernel is not loaded from flash 488 + to RAM. Read-write sections, such as the data section and stack, 489 + are still copied to RAM. The XIP kernel is not compressed since 490 + it has to run directly from flash, so it will take more space to 491 + store it. The flash address used to link the kernel object files, 492 + and for storing it, is configuration dependent. Therefore, if you 493 + say Y here, you must know the proper physical address where to 494 + store the kernel image depending on your own flash memory usage. 495 + 496 + Also note that the make target becomes "make xipImage" rather than 497 + "make Image" or "make uImage". The final kernel binary to put in 498 + ROM memory will be arch/xtensa/boot/xipImage. 499 + 500 + If unsure, say N. 501 + 485 502 config MEMMAP_CACHEATTR 486 503 hex "Cache attributes for the memory address space" 487 504 depends on !MMU ··· 547 522 548 523 If unsure, leave the default value here. 549 524 525 + config KERNEL_VIRTUAL_ADDRESS 526 + hex "Kernel virtual address" 527 + depends on MMU && XIP_KERNEL 528 + default 0xd0003000 529 + help 530 + This is the virtual address where the XIP kernel is mapped. 531 + XIP kernel may be mapped into KSEG or KIO region, virtual address 532 + provided here must match kernel load address provided in 533 + KERNEL_LOAD_ADDRESS. 534 + 550 535 config KERNEL_LOAD_ADDRESS 551 536 hex "Kernel load address" 552 537 default 0x60003000 if !MMU ··· 572 537 config VECTORS_OFFSET 573 538 hex "Kernel vectors offset" 574 539 default 0x00003000 540 + depends on !XIP_KERNEL 575 541 help 576 542 This is the offset of the kernel image from the relocatable vectors 577 543 base. 578 544 579 545 If unsure, leave the default value here. 546 + 547 + config XIP_DATA_ADDR 548 + hex "XIP kernel data virtual address" 549 + depends on XIP_KERNEL 550 + default 0x00000000 551 + help 552 + This is the virtual address where XIP kernel data is copied. 553 + It must be within KSEG if MMU is used. 580 554 581 555 config PLATFORM_WANT_DEFAULT_MEM 582 556 def_bool n
+2 -1
arch/xtensa/Makefile
··· 87 87 88 88 boot := arch/xtensa/boot 89 89 90 - all Image zImage uImage: vmlinux 90 + all Image zImage uImage xipImage: vmlinux 91 91 $(Q)$(MAKE) $(build)=$(boot) $@ 92 92 93 93 archheaders: ··· 97 97 @echo '* Image - Kernel ELF image with reset vector' 98 98 @echo '* zImage - Compressed kernel image (arch/xtensa/boot/images/zImage.*)' 99 99 @echo '* uImage - U-Boot wrapped image' 100 + @echo ' xipImage - XIP image' 100 101 endef
+5
arch/xtensa/boot/Makefile
··· 29 29 Image: boot-elf 30 30 zImage: boot-redboot 31 31 uImage: $(obj)/uImage 32 + xipImage: $(obj)/xipImage 32 33 33 34 boot-elf boot-redboot: $(addprefix $(obj)/,$(subdir-y)) 34 35 $(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS) ··· 50 49 51 50 $(obj)/uImage: vmlinux.bin.gz FORCE 52 51 $(call if_changed,uimage) 52 + $(Q)$(kecho) ' Kernel: $@ is ready' 53 + 54 + $(obj)/xipImage: vmlinux FORCE 55 + $(call if_changed,objcopy) 53 56 $(Q)$(kecho) ' Kernel: $@ is ready'
+119
arch/xtensa/configs/xip_kc705_defconfig
··· 1 + CONFIG_SYSVIPC=y 2 + CONFIG_POSIX_MQUEUE=y 3 + CONFIG_NO_HZ_IDLE=y 4 + CONFIG_HIGH_RES_TIMERS=y 5 + CONFIG_PREEMPT=y 6 + CONFIG_IRQ_TIME_ACCOUNTING=y 7 + CONFIG_BSD_PROCESS_ACCT=y 8 + CONFIG_MEMCG=y 9 + CONFIG_CGROUP_FREEZER=y 10 + CONFIG_CGROUP_DEVICE=y 11 + CONFIG_CGROUP_CPUACCT=y 12 + CONFIG_CGROUP_DEBUG=y 13 + CONFIG_NAMESPACES=y 14 + CONFIG_SCHED_AUTOGROUP=y 15 + CONFIG_RELAY=y 16 + CONFIG_BLK_DEV_INITRD=y 17 + CONFIG_EXPERT=y 18 + CONFIG_KALLSYMS_ALL=y 19 + CONFIG_PROFILING=y 20 + CONFIG_XTENSA_VARIANT_DC233C=y 21 + CONFIG_XTENSA_UNALIGNED_USER=y 22 + CONFIG_XIP_KERNEL=y 23 + CONFIG_XIP_DATA_ADDR=0xd0000000 24 + CONFIG_KERNEL_VIRTUAL_ADDRESS=0xe6000000 25 + CONFIG_KERNEL_LOAD_ADDRESS=0xf6000000 26 + CONFIG_XTENSA_KSEG_512M=y 27 + CONFIG_HIGHMEM=y 28 + CONFIG_XTENSA_PLATFORM_XTFPGA=y 29 + CONFIG_CMDLINE_BOOL=y 30 + CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000@0" 31 + CONFIG_USE_OF=y 32 + CONFIG_BUILTIN_DTB_SOURCE="kc705" 33 + # CONFIG_PARSE_BOOTPARAM is not set 34 + CONFIG_OPROFILE=y 35 + # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set 36 + # CONFIG_COMPACTION is not set 37 + CONFIG_NET=y 38 + CONFIG_PACKET=y 39 + CONFIG_UNIX=y 40 + CONFIG_INET=y 41 + CONFIG_IP_MULTICAST=y 42 + CONFIG_IP_PNP=y 43 + CONFIG_IP_PNP_DHCP=y 44 + CONFIG_IP_PNP_BOOTP=y 45 + CONFIG_IP_PNP_RARP=y 46 + # CONFIG_IPV6 is not set 47 + CONFIG_NETFILTER=y 48 + # CONFIG_WIRELESS is not set 49 + CONFIG_UEVENT_HELPER=y 50 + CONFIG_DEVTMPFS=y 51 + CONFIG_DEVTMPFS_MOUNT=y 52 + # CONFIG_STANDALONE is not set 53 + CONFIG_BLK_DEV_LOOP=y 54 + CONFIG_BLK_DEV_RAM=y 55 + CONFIG_SCSI=y 56 + CONFIG_BLK_DEV_SD=y 57 + CONFIG_NETDEVICES=y 58 + # CONFIG_NET_VENDOR_ARC is not set 59 + # CONFIG_NET_VENDOR_AURORA is not set 60 + # CONFIG_NET_VENDOR_BROADCOM is not set 61 + # CONFIG_NET_VENDOR_INTEL is not set 62 + # CONFIG_NET_VENDOR_MARVELL is not set 63 + # CONFIG_NET_VENDOR_MICREL is not set 64 + # CONFIG_NET_VENDOR_NATSEMI is not set 65 + # CONFIG_NET_VENDOR_SAMSUNG is not set 66 + # CONFIG_NET_VENDOR_SEEQ is not set 67 + # CONFIG_NET_VENDOR_SMSC is not set 68 + # CONFIG_NET_VENDOR_STMICRO is not set 69 + # CONFIG_NET_VENDOR_VIA is not set 70 + # CONFIG_NET_VENDOR_WIZNET is not set 71 + CONFIG_MARVELL_PHY=y 72 + # CONFIG_WLAN is not set 73 + # CONFIG_INPUT_KEYBOARD is not set 74 + # CONFIG_INPUT_MOUSE is not set 75 + # CONFIG_SERIO is not set 76 + CONFIG_DEVKMEM=y 77 + CONFIG_SERIAL_8250=y 78 + # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set 79 + CONFIG_SERIAL_8250_CONSOLE=y 80 + CONFIG_SERIAL_OF_PLATFORM=y 81 + # CONFIG_HWMON is not set 82 + CONFIG_WATCHDOG=y 83 + CONFIG_WATCHDOG_NOWAYOUT=y 84 + CONFIG_SOFT_WATCHDOG=y 85 + # CONFIG_VGA_CONSOLE is not set 86 + # CONFIG_USB_SUPPORT is not set 87 + # CONFIG_IOMMU_SUPPORT is not set 88 + CONFIG_EXT3_FS=y 89 + CONFIG_FANOTIFY=y 90 + CONFIG_VFAT_FS=y 91 + CONFIG_PROC_KCORE=y 92 + CONFIG_TMPFS=y 93 + CONFIG_TMPFS_POSIX_ACL=y 94 + CONFIG_NFS_FS=y 95 + CONFIG_NFS_V4=y 96 + CONFIG_NFS_SWAP=y 97 + CONFIG_ROOT_NFS=y 98 + CONFIG_SUNRPC_DEBUG=y 99 + CONFIG_NLS_CODEPAGE_437=y 100 + CONFIG_NLS_ISO8859_1=y 101 + CONFIG_CRYPTO_ECHAINIV=y 102 + CONFIG_CRYPTO_DEFLATE=y 103 + CONFIG_CRYPTO_LZO=y 104 + CONFIG_CRYPTO_ANSI_CPRNG=y 105 + CONFIG_PRINTK_TIME=y 106 + CONFIG_DYNAMIC_DEBUG=y 107 + CONFIG_DEBUG_INFO=y 108 + CONFIG_MAGIC_SYSRQ=y 109 + CONFIG_DETECT_HUNG_TASK=y 110 + # CONFIG_SCHED_DEBUG is not set 111 + CONFIG_SCHEDSTATS=y 112 + CONFIG_DEBUG_RT_MUTEXES=y 113 + CONFIG_DEBUG_SPINLOCK=y 114 + CONFIG_DEBUG_MUTEXES=y 115 + CONFIG_DEBUG_ATOMIC_SLEEP=y 116 + CONFIG_STACKTRACE=y 117 + CONFIG_RCU_TRACE=y 118 + # CONFIG_FTRACE is not set 119 + # CONFIG_S32C1I_SELFTEST is not set
+6
arch/xtensa/include/asm/cache.h
··· 31 31 32 32 #define ARCH_DMA_MINALIGN L1_CACHE_BYTES 33 33 34 + /* 35 + * R/O after init is actually writable, it cannot go to .rodata 36 + * according to vmlinux linker script. 37 + */ 38 + #define __ro_after_init __read_mostly 39 + 34 40 #endif /* _XTENSA_CACHE_H */
+11
arch/xtensa/include/asm/page.h
··· 169 169 if (off >= XCHAL_KSEG_SIZE) 170 170 off -= XCHAL_KSEG_SIZE; 171 171 172 + #ifndef CONFIG_XIP_KERNEL 172 173 return off + PHYS_OFFSET; 174 + #else 175 + if (off < XCHAL_KSEG_SIZE) 176 + return off + PHYS_OFFSET; 177 + 178 + off -= XCHAL_KSEG_SIZE; 179 + if (off >= XCHAL_KIO_SIZE) 180 + off -= XCHAL_KIO_SIZE; 181 + 182 + return off + XCHAL_KIO_PADDR; 183 + #endif 173 184 } 174 185 #define __pa(x) ___pa((unsigned long)(x)) 175 186 #else
+4
arch/xtensa/include/asm/vectors.h
··· 22 22 #include <asm/kmem_layout.h> 23 23 24 24 #if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY 25 + #ifdef CONFIG_KERNEL_VIRTUAL_ADDRESS 26 + #define KERNELOFFSET CONFIG_KERNEL_VIRTUAL_ADDRESS 27 + #else 25 28 #define KERNELOFFSET (CONFIG_KERNEL_LOAD_ADDRESS + \ 26 29 XCHAL_KSEG_CACHED_VADDR - \ 27 30 XCHAL_KSEG_PADDR) 31 + #endif 28 32 #else 29 33 #define KERNELOFFSET CONFIG_KERNEL_LOAD_ADDRESS 30 34 #endif
+7
arch/xtensa/kernel/head.S
··· 260 260 ___invalidate_icache_all a2 a3 261 261 isync 262 262 263 + #ifdef CONFIG_XIP_KERNEL 264 + /* Setup bootstrap CPU stack in XIP kernel */ 265 + 266 + movi a1, start_info 267 + l32i a1, a1, 0 268 + #endif 269 + 263 270 movi a6, 0 264 271 xsr a6, excsave1 265 272
+7
arch/xtensa/kernel/setup.c
··· 308 308 extern char _SecondaryResetVector_text_start; 309 309 extern char _SecondaryResetVector_text_end; 310 310 #endif 311 + #ifdef CONFIG_XIP_KERNEL 312 + extern char _xip_start[]; 313 + extern char _xip_end[]; 314 + #endif 311 315 312 316 static inline int __init_memblock mem_reserve(unsigned long start, 313 317 unsigned long end) ··· 343 339 #endif 344 340 345 341 mem_reserve(__pa(_stext), __pa(_end)); 342 + #ifdef CONFIG_XIP_KERNEL 343 + mem_reserve(__pa(_xip_start), __pa(_xip_end)); 344 + #endif 346 345 347 346 #ifdef CONFIG_VECTORS_OFFSET 348 347 mem_reserve(__pa(&_WindowVectors_text_start),
+50 -2
arch/xtensa/kernel/vmlinux.lds.S
··· 134 134 NOTES 135 135 /* Data section */ 136 136 137 + #ifdef CONFIG_XIP_KERNEL 138 + INIT_TEXT_SECTION(PAGE_SIZE) 139 + #else 137 140 _sdata = .; 138 141 RW_DATA_SECTION(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE) 139 142 _edata = .; ··· 150 147 .init.data : 151 148 { 152 149 INIT_DATA 150 + } 151 + #endif 152 + 153 + .init.rodata : 154 + { 153 155 . = ALIGN(0x4); 154 156 __tagtable_begin = .; 155 157 *(.taglist) ··· 195 187 RELOCATE_ENTRY(_DebugInterruptVector_text, 196 188 .DebugInterruptVector.text); 197 189 #endif 190 + #ifdef CONFIG_XIP_KERNEL 191 + RELOCATE_ENTRY(_xip_data, .data); 192 + RELOCATE_ENTRY(_xip_init_data, .init.data); 193 + #else 198 194 #if defined(CONFIG_SMP) 199 195 RELOCATE_ENTRY(_SecondaryResetVector_text, 200 196 .SecondaryResetVector.text); 201 197 #endif 198 + #endif 202 199 203 - 204 200 __boot_reloc_table_end = ABSOLUTE(.) ; 205 201 206 202 INIT_SETUP(XCHAL_ICACHE_LINESIZE) ··· 290 278 . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3; 291 279 292 280 #endif 293 - #if defined(CONFIG_SMP) 281 + #if !defined(CONFIG_XIP_KERNEL) && defined(CONFIG_SMP) 294 282 295 283 SECTION_VECTOR (_SecondaryResetVector_text, 296 284 .SecondaryResetVector.text, ··· 303 291 304 292 . = ALIGN(PAGE_SIZE); 305 293 294 + #ifndef CONFIG_XIP_KERNEL 306 295 __init_end = .; 307 296 308 297 BSS_SECTION(0, 8192, 0) 298 + #endif 309 299 310 300 _end = .; 301 + 302 + #ifdef CONFIG_XIP_KERNEL 303 + . = CONFIG_XIP_DATA_ADDR; 304 + 305 + _xip_start = .; 306 + 307 + #undef LOAD_OFFSET 308 + #define LOAD_OFFSET \ 309 + (CONFIG_XIP_DATA_ADDR - (LOADADDR(.dummy) + SIZEOF(.dummy) + 3) & ~ 3) 310 + 311 + _xip_data_start = .; 312 + _sdata = .; 313 + RW_DATA_SECTION(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE) 314 + _edata = .; 315 + _xip_data_end = .; 316 + 317 + /* Initialization data: */ 318 + 319 + STRUCT_ALIGN(); 320 + 321 + _xip_init_data_start = .; 322 + __init_begin = .; 323 + .init.data : 324 + { 325 + INIT_DATA 326 + } 327 + _xip_init_data_end = .; 328 + __init_end = .; 329 + BSS_SECTION(0, 8192, 0) 330 + 331 + _xip_end = .; 332 + 333 + #undef LOAD_OFFSET 334 + #endif 311 335 312 336 DWARF_DEBUG 313 337