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>
This commit is contained in:
parent
76743c0e09
commit
7af710d988
|
@ -19,8 +19,8 @@ config XTENSA
|
|||
select GENERIC_PCI_IOMAP
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_STRNCPY_FROM_USER if KASAN
|
||||
select HAVE_ARCH_JUMP_LABEL
|
||||
select HAVE_ARCH_KASAN if MMU
|
||||
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
|
||||
select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_DEBUG_KMEMLEAK
|
||||
select HAVE_DMA_CONTIGUOUS
|
||||
|
@ -299,6 +299,9 @@ config XTENSA_CALIBRATE_CCOUNT
|
|||
config SERIAL_CONSOLE
|
||||
def_bool n
|
||||
|
||||
config PLATFORM_HAVE_XIP
|
||||
def_bool n
|
||||
|
||||
menu "Platform options"
|
||||
|
||||
choice
|
||||
|
@ -325,6 +328,7 @@ config XTENSA_PLATFORM_XTFPGA
|
|||
select PLATFORM_WANT_DEFAULT_MEM if !MMU
|
||||
select SERIAL_CONSOLE
|
||||
select XTENSA_CALIBRATE_CCOUNT
|
||||
select PLATFORM_HAVE_XIP
|
||||
help
|
||||
XTFPGA is the name of Tensilica board family (LX60, LX110, LX200, ML605).
|
||||
This hardware is capable of running a full Linux distribution.
|
||||
|
@ -478,6 +482,27 @@ config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
|
|||
|
||||
If in doubt, say Y.
|
||||
|
||||
config XIP_KERNEL
|
||||
bool "Kernel Execute-In-Place from ROM"
|
||||
depends on PLATFORM_HAVE_XIP
|
||||
help
|
||||
Execute-In-Place allows the kernel to run from non-volatile storage
|
||||
directly addressable by the CPU, such as NOR flash. This saves RAM
|
||||
space since the text section of the kernel is not loaded from flash
|
||||
to RAM. Read-write sections, such as the data section and stack,
|
||||
are still copied to RAM. The XIP kernel is not compressed since
|
||||
it has to run directly from flash, so it will take more space to
|
||||
store it. The flash address used to link the kernel object files,
|
||||
and for storing it, is configuration dependent. Therefore, if you
|
||||
say Y here, you must know the proper physical address where to
|
||||
store the kernel image depending on your own flash memory usage.
|
||||
|
||||
Also note that the make target becomes "make xipImage" rather than
|
||||
"make Image" or "make uImage". The final kernel binary to put in
|
||||
ROM memory will be arch/xtensa/boot/xipImage.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config MEMMAP_CACHEATTR
|
||||
hex "Cache attributes for the memory address space"
|
||||
depends on !MMU
|
||||
|
@ -522,6 +547,16 @@ config KSEG_PADDR
|
|||
|
||||
If unsure, leave the default value here.
|
||||
|
||||
config KERNEL_VIRTUAL_ADDRESS
|
||||
hex "Kernel virtual address"
|
||||
depends on MMU && XIP_KERNEL
|
||||
default 0xd0003000
|
||||
help
|
||||
This is the virtual address where the XIP kernel is mapped.
|
||||
XIP kernel may be mapped into KSEG or KIO region, virtual address
|
||||
provided here must match kernel load address provided in
|
||||
KERNEL_LOAD_ADDRESS.
|
||||
|
||||
config KERNEL_LOAD_ADDRESS
|
||||
hex "Kernel load address"
|
||||
default 0x60003000 if !MMU
|
||||
|
@ -537,12 +572,21 @@ config KERNEL_LOAD_ADDRESS
|
|||
config VECTORS_OFFSET
|
||||
hex "Kernel vectors offset"
|
||||
default 0x00003000
|
||||
depends on !XIP_KERNEL
|
||||
help
|
||||
This is the offset of the kernel image from the relocatable vectors
|
||||
base.
|
||||
|
||||
If unsure, leave the default value here.
|
||||
|
||||
config XIP_DATA_ADDR
|
||||
hex "XIP kernel data virtual address"
|
||||
depends on XIP_KERNEL
|
||||
default 0x00000000
|
||||
help
|
||||
This is the virtual address where XIP kernel data is copied.
|
||||
It must be within KSEG if MMU is used.
|
||||
|
||||
config PLATFORM_WANT_DEFAULT_MEM
|
||||
def_bool n
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ drivers-$(CONFIG_OPROFILE) += arch/xtensa/oprofile/
|
|||
|
||||
boot := arch/xtensa/boot
|
||||
|
||||
all Image zImage uImage: vmlinux
|
||||
all Image zImage uImage xipImage: vmlinux
|
||||
$(Q)$(MAKE) $(build)=$(boot) $@
|
||||
|
||||
archheaders:
|
||||
|
@ -97,4 +97,5 @@ define archhelp
|
|||
@echo '* Image - Kernel ELF image with reset vector'
|
||||
@echo '* zImage - Compressed kernel image (arch/xtensa/boot/images/zImage.*)'
|
||||
@echo '* uImage - U-Boot wrapped image'
|
||||
@echo ' xipImage - XIP image'
|
||||
endef
|
||||
|
|
|
@ -29,6 +29,7 @@ all: $(boot-y)
|
|||
Image: boot-elf
|
||||
zImage: boot-redboot
|
||||
uImage: $(obj)/uImage
|
||||
xipImage: $(obj)/xipImage
|
||||
|
||||
boot-elf boot-redboot: $(addprefix $(obj)/,$(subdir-y))
|
||||
$(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS)
|
||||
|
@ -50,3 +51,7 @@ UIMAGE_COMPRESSION = gzip
|
|||
$(obj)/uImage: vmlinux.bin.gz FORCE
|
||||
$(call if_changed,uimage)
|
||||
$(Q)$(kecho) ' Kernel: $@ is ready'
|
||||
|
||||
$(obj)/xipImage: vmlinux FORCE
|
||||
$(call if_changed,objcopy)
|
||||
$(Q)$(kecho) ' Kernel: $@ is ready'
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_PREEMPT=y
|
||||
CONFIG_IRQ_TIME_ACCOUNTING=y
|
||||
CONFIG_BSD_PROCESS_ACCT=y
|
||||
CONFIG_MEMCG=y
|
||||
CONFIG_CGROUP_FREEZER=y
|
||||
CONFIG_CGROUP_DEVICE=y
|
||||
CONFIG_CGROUP_CPUACCT=y
|
||||
CONFIG_CGROUP_DEBUG=y
|
||||
CONFIG_NAMESPACES=y
|
||||
CONFIG_SCHED_AUTOGROUP=y
|
||||
CONFIG_RELAY=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_EXPERT=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_XTENSA_VARIANT_DC233C=y
|
||||
CONFIG_XTENSA_UNALIGNED_USER=y
|
||||
CONFIG_XIP_KERNEL=y
|
||||
CONFIG_XIP_DATA_ADDR=0xd0000000
|
||||
CONFIG_KERNEL_VIRTUAL_ADDRESS=0xe6000000
|
||||
CONFIG_KERNEL_LOAD_ADDRESS=0xf6000000
|
||||
CONFIG_XTENSA_KSEG_512M=y
|
||||
CONFIG_HIGHMEM=y
|
||||
CONFIG_XTENSA_PLATFORM_XTFPGA=y
|
||||
CONFIG_CMDLINE_BOOL=y
|
||||
CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000@0"
|
||||
CONFIG_USE_OF=y
|
||||
CONFIG_BUILTIN_DTB_SOURCE="kc705"
|
||||
# CONFIG_PARSE_BOOTPARAM is not set
|
||||
CONFIG_OPROFILE=y
|
||||
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
||||
# CONFIG_COMPACTION is not set
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_INET=y
|
||||
CONFIG_IP_MULTICAST=y
|
||||
CONFIG_IP_PNP=y
|
||||
CONFIG_IP_PNP_DHCP=y
|
||||
CONFIG_IP_PNP_BOOTP=y
|
||||
CONFIG_IP_PNP_RARP=y
|
||||
# CONFIG_IPV6 is not set
|
||||
CONFIG_NETFILTER=y
|
||||
# CONFIG_WIRELESS is not set
|
||||
CONFIG_UEVENT_HELPER=y
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
# CONFIG_STANDALONE is not set
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_NETDEVICES=y
|
||||
# CONFIG_NET_VENDOR_ARC is not set
|
||||
# CONFIG_NET_VENDOR_AURORA is not set
|
||||
# CONFIG_NET_VENDOR_BROADCOM is not set
|
||||
# CONFIG_NET_VENDOR_INTEL is not set
|
||||
# CONFIG_NET_VENDOR_MARVELL is not set
|
||||
# CONFIG_NET_VENDOR_MICREL is not set
|
||||
# CONFIG_NET_VENDOR_NATSEMI is not set
|
||||
# CONFIG_NET_VENDOR_SAMSUNG is not set
|
||||
# CONFIG_NET_VENDOR_SEEQ is not set
|
||||
# CONFIG_NET_VENDOR_SMSC is not set
|
||||
# CONFIG_NET_VENDOR_STMICRO is not set
|
||||
# CONFIG_NET_VENDOR_VIA is not set
|
||||
# CONFIG_NET_VENDOR_WIZNET is not set
|
||||
CONFIG_MARVELL_PHY=y
|
||||
# CONFIG_WLAN is not set
|
||||
# CONFIG_INPUT_KEYBOARD is not set
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
# CONFIG_SERIO is not set
|
||||
CONFIG_DEVKMEM=y
|
||||
CONFIG_SERIAL_8250=y
|
||||
# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_WATCHDOG=y
|
||||
CONFIG_WATCHDOG_NOWAYOUT=y
|
||||
CONFIG_SOFT_WATCHDOG=y
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
# CONFIG_USB_SUPPORT is not set
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_EXT3_FS=y
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_PROC_KCORE=y
|
||||
CONFIG_TMPFS=y
|
||||
CONFIG_TMPFS_POSIX_ACL=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_SUNRPC_DEBUG=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_CRYPTO_ECHAINIV=y
|
||||
CONFIG_CRYPTO_DEFLATE=y
|
||||
CONFIG_CRYPTO_LZO=y
|
||||
CONFIG_CRYPTO_ANSI_CPRNG=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_DYNAMIC_DEBUG=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_SCHEDSTATS=y
|
||||
CONFIG_DEBUG_RT_MUTEXES=y
|
||||
CONFIG_DEBUG_SPINLOCK=y
|
||||
CONFIG_DEBUG_MUTEXES=y
|
||||
CONFIG_DEBUG_ATOMIC_SLEEP=y
|
||||
CONFIG_STACKTRACE=y
|
||||
CONFIG_RCU_TRACE=y
|
||||
# CONFIG_FTRACE is not set
|
||||
# CONFIG_S32C1I_SELFTEST is not set
|
|
@ -31,4 +31,10 @@
|
|||
|
||||
#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
|
||||
|
||||
/*
|
||||
* R/O after init is actually writable, it cannot go to .rodata
|
||||
* according to vmlinux linker script.
|
||||
*/
|
||||
#define __ro_after_init __read_mostly
|
||||
|
||||
#endif /* _XTENSA_CACHE_H */
|
||||
|
|
|
@ -169,7 +169,18 @@ static inline unsigned long ___pa(unsigned long va)
|
|||
if (off >= XCHAL_KSEG_SIZE)
|
||||
off -= XCHAL_KSEG_SIZE;
|
||||
|
||||
#ifndef CONFIG_XIP_KERNEL
|
||||
return off + PHYS_OFFSET;
|
||||
#else
|
||||
if (off < XCHAL_KSEG_SIZE)
|
||||
return off + PHYS_OFFSET;
|
||||
|
||||
off -= XCHAL_KSEG_SIZE;
|
||||
if (off >= XCHAL_KIO_SIZE)
|
||||
off -= XCHAL_KIO_SIZE;
|
||||
|
||||
return off + XCHAL_KIO_PADDR;
|
||||
#endif
|
||||
}
|
||||
#define __pa(x) ___pa((unsigned long)(x))
|
||||
#else
|
||||
|
|
|
@ -22,9 +22,13 @@
|
|||
#include <asm/kmem_layout.h>
|
||||
|
||||
#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
|
||||
#ifdef CONFIG_KERNEL_VIRTUAL_ADDRESS
|
||||
#define KERNELOFFSET CONFIG_KERNEL_VIRTUAL_ADDRESS
|
||||
#else
|
||||
#define KERNELOFFSET (CONFIG_KERNEL_LOAD_ADDRESS + \
|
||||
XCHAL_KSEG_CACHED_VADDR - \
|
||||
XCHAL_KSEG_PADDR)
|
||||
#endif
|
||||
#else
|
||||
#define KERNELOFFSET CONFIG_KERNEL_LOAD_ADDRESS
|
||||
#endif
|
||||
|
|
|
@ -260,6 +260,13 @@ ENTRY(_startup)
|
|||
___invalidate_icache_all a2 a3
|
||||
isync
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
/* Setup bootstrap CPU stack in XIP kernel */
|
||||
|
||||
movi a1, start_info
|
||||
l32i a1, a1, 0
|
||||
#endif
|
||||
|
||||
movi a6, 0
|
||||
xsr a6, excsave1
|
||||
|
||||
|
|
|
@ -308,6 +308,10 @@ extern char _Level6InterruptVector_text_end;
|
|||
extern char _SecondaryResetVector_text_start;
|
||||
extern char _SecondaryResetVector_text_end;
|
||||
#endif
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
extern char _xip_start[];
|
||||
extern char _xip_end[];
|
||||
#endif
|
||||
|
||||
static inline int __init_memblock mem_reserve(unsigned long start,
|
||||
unsigned long end)
|
||||
|
@ -339,6 +343,9 @@ void __init setup_arch(char **cmdline_p)
|
|||
#endif
|
||||
|
||||
mem_reserve(__pa(_stext), __pa(_end));
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
mem_reserve(__pa(_xip_start), __pa(_xip_end));
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VECTORS_OFFSET
|
||||
mem_reserve(__pa(&_WindowVectors_text_start),
|
||||
|
|
|
@ -134,6 +134,9 @@ SECTIONS
|
|||
NOTES
|
||||
/* Data section */
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
INIT_TEXT_SECTION(PAGE_SIZE)
|
||||
#else
|
||||
_sdata = .;
|
||||
RW_DATA_SECTION(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE)
|
||||
_edata = .;
|
||||
|
@ -147,6 +150,11 @@ SECTIONS
|
|||
.init.data :
|
||||
{
|
||||
INIT_DATA
|
||||
}
|
||||
#endif
|
||||
|
||||
.init.rodata :
|
||||
{
|
||||
. = ALIGN(0x4);
|
||||
__tagtable_begin = .;
|
||||
*(.taglist)
|
||||
|
@ -187,12 +195,16 @@ SECTIONS
|
|||
RELOCATE_ENTRY(_DebugInterruptVector_text,
|
||||
.DebugInterruptVector.text);
|
||||
#endif
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
RELOCATE_ENTRY(_xip_data, .data);
|
||||
RELOCATE_ENTRY(_xip_init_data, .init.data);
|
||||
#else
|
||||
#if defined(CONFIG_SMP)
|
||||
RELOCATE_ENTRY(_SecondaryResetVector_text,
|
||||
.SecondaryResetVector.text);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
__boot_reloc_table_end = ABSOLUTE(.) ;
|
||||
|
||||
INIT_SETUP(XCHAL_ICACHE_LINESIZE)
|
||||
|
@ -278,7 +290,7 @@ SECTIONS
|
|||
. = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
|
||||
|
||||
#endif
|
||||
#if defined(CONFIG_SMP)
|
||||
#if !defined(CONFIG_XIP_KERNEL) && defined(CONFIG_SMP)
|
||||
|
||||
SECTION_VECTOR (_SecondaryResetVector_text,
|
||||
.SecondaryResetVector.text,
|
||||
|
@ -291,12 +303,48 @@ SECTIONS
|
|||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
|
||||
#ifndef CONFIG_XIP_KERNEL
|
||||
__init_end = .;
|
||||
|
||||
BSS_SECTION(0, 8192, 0)
|
||||
#endif
|
||||
|
||||
_end = .;
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
. = CONFIG_XIP_DATA_ADDR;
|
||||
|
||||
_xip_start = .;
|
||||
|
||||
#undef LOAD_OFFSET
|
||||
#define LOAD_OFFSET \
|
||||
(CONFIG_XIP_DATA_ADDR - (LOADADDR(.dummy) + SIZEOF(.dummy) + 3) & ~ 3)
|
||||
|
||||
_xip_data_start = .;
|
||||
_sdata = .;
|
||||
RW_DATA_SECTION(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE)
|
||||
_edata = .;
|
||||
_xip_data_end = .;
|
||||
|
||||
/* Initialization data: */
|
||||
|
||||
STRUCT_ALIGN();
|
||||
|
||||
_xip_init_data_start = .;
|
||||
__init_begin = .;
|
||||
.init.data :
|
||||
{
|
||||
INIT_DATA
|
||||
}
|
||||
_xip_init_data_end = .;
|
||||
__init_end = .;
|
||||
BSS_SECTION(0, 8192, 0)
|
||||
|
||||
_xip_end = .;
|
||||
|
||||
#undef LOAD_OFFSET
|
||||
#endif
|
||||
|
||||
DWARF_DEBUG
|
||||
|
||||
.xt.prop 0 : { KEEP(*(.xt.prop .xt.prop.* .gnu.linkonce.prop.*)) }
|
||||
|
|
Loading…
Reference in New Issue