[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v1 7/9] xen/common: dom0less: introduce common kernel.c
The following functions don't have arch specific things so it is moved to common: - kernel_prboe() - kernel_load() - output_length() Functions necessary for dom0less are only moved. The following changes are done: - Swap __init and return type of kernel_decompress() function to be consistent with defintions of functions in other files. The same for output_length(). - Wrap by "ifdef CONFIG_ARM" the call of kernel_uimage_probe() in kernel_probe() as uImage isn't really used nowadays thereby leave kernel_uimage_probe() call here just for compatability with Arm code. - Introduce kernel_zimage_probe() to cover the case that arch can have different zimage header. - Add ASSERT() for kernel_load() to check that it argument isn't NULL. - Make kernel_uimage_probe() non-static in Arm's code as it is used in common/kernel.c. Introduce CONFIG_DOMAIN_BUILD_HELPERS to not provide stubs for archs which doesn't provice enough functionality to enable it. Select CONFIG_DOMAIN_BUILD_HELPERS for CONFIG_ARM as only Arm supports it, at the moment. Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx> --- xen/arch/arm/Kconfig | 1 + xen/arch/arm/kernel.c | 221 +--------------------------- xen/common/Kconfig | 11 +- xen/common/device-tree/Makefile | 1 + xen/common/device-tree/kernel.c | 242 +++++++++++++++++++++++++++++++ xen/include/asm-generic/kernel.h | 13 ++ 6 files changed, 272 insertions(+), 217 deletions(-) create mode 100644 xen/common/device-tree/kernel.c diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig index eff6ea6b6d..8a8681ef3b 100644 --- a/xen/arch/arm/Kconfig +++ b/xen/arch/arm/Kconfig @@ -12,6 +12,7 @@ config ARM_64 config ARM def_bool y + select DOMAIN_BUILD_HELPERS select FUNCTION_ALIGNMENT_4B select GENERIC_UART_INIT select HAS_ALTERNATIVE if HAS_VMAP diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c index b75bd6a887..8e5fd09c75 100644 --- a/xen/arch/arm/kernel.c +++ b/xen/arch/arm/kernel.c @@ -160,105 +160,6 @@ static void __init kernel_zimage_load(struct kernel_info *info) iounmap(kernel); } -static __init uint32_t output_length(char *image, unsigned long image_len) -{ - return *(uint32_t *)&image[image_len - 4]; -} - -static __init int kernel_decompress(struct bootmodule *mod, uint32_t offset) -{ - char *output, *input; - char magic[2]; - int rc; - unsigned int kernel_order_out; - paddr_t output_size; - struct page_info *pages; - mfn_t mfn; - int i; - paddr_t addr = mod->start; - paddr_t size = mod->size; - - if ( size < offset ) - return -EINVAL; - - /* - * It might be that gzip header does not appear at the start address - * (e.g. in case of compressed uImage) so take into account offset to - * gzip header. - */ - addr += offset; - size -= offset; - - if ( size < 2 ) - return -EINVAL; - - copy_from_paddr(magic, addr, sizeof(magic)); - - /* only gzip is supported */ - if ( !gzip_check(magic, size) ) - return -EINVAL; - - input = ioremap_cache(addr, size); - if ( input == NULL ) - return -EFAULT; - - output_size = output_length(input, size); - kernel_order_out = get_order_from_bytes(output_size); - pages = alloc_domheap_pages(NULL, kernel_order_out, 0); - if ( pages == NULL ) - { - iounmap(input); - return -ENOMEM; - } - mfn = page_to_mfn(pages); - output = vmap_contig(mfn, 1 << kernel_order_out); - - rc = perform_gunzip(output, input, size); - clean_dcache_va_range(output, output_size); - iounmap(input); - vunmap(output); - - if ( rc ) - { - free_domheap_pages(pages, kernel_order_out); - return rc; - } - - mod->start = page_to_maddr(pages); - mod->size = output_size; - - /* - * Need to free pages after output_size here because they won't be - * freed by discard_initial_modules - */ - i = PFN_UP(output_size); - for ( ; i < (1 << kernel_order_out); i++ ) - free_domheap_page(pages + i); - - /* - * When using static heap feature, don't give bootmodules memory back to - * the heap allocator - */ - if ( using_static_heap ) - return 0; - - /* - * When freeing the kernel, we need to pass the module start address and - * size as they were before taking an offset to gzip header into account, - * so that the entire region will be freed. - */ - addr -= offset; - size += offset; - - /* - * Free the original kernel, update the pointers to the - * decompressed kernel - */ - fw_unreserved_regions(addr, addr + size, init_domheap_pages, 0); - - return 0; -} - /* * Uimage CPU Architecture Codes */ @@ -271,8 +172,8 @@ static __init int kernel_decompress(struct bootmodule *mod, uint32_t offset) /* * Check if the image is a uImage and setup kernel_info */ -static int __init kernel_uimage_probe(struct kernel_info *info, - struct bootmodule *mod) +int __init kernel_uimage_probe(struct kernel_info *info, + struct bootmodule *mod) { struct { __be32 magic; /* Image Header Magic Number */ @@ -502,130 +403,20 @@ static int __init kernel_zimage32_probe(struct kernel_info *info, return 0; } -int __init kernel_probe(struct kernel_info *info, - const struct dt_device_node *domain) +int __init kernel_zimage_probe(struct kernel_info *info, paddr_t addr, + paddr_t size) { - struct bootmodule *mod = NULL; - struct bootcmdline *cmd = NULL; - struct dt_device_node *node; - u64 kernel_addr, initrd_addr, dtb_addr, size; int rc; - /* - * We need to initialize start to 0. This field may be populated during - * kernel_xxx_probe() if the image has a fixed entry point (for e.g. - * uimage.ep). - * We will use this to determine if the image has a fixed entry point or - * the load address should be used as the start address. - */ - info->entry = 0; - - /* domain is NULL only for the hardware domain */ - if ( domain == NULL ) - { - ASSERT(is_hardware_domain(info->d)); - - mod = boot_module_find_by_kind(BOOTMOD_KERNEL); - - info->kernel_bootmodule = mod; - info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK); - - cmd = boot_cmdline_find_by_kind(BOOTMOD_KERNEL); - if ( cmd ) - info->cmdline = &cmd->cmdline[0]; - } - else - { - const char *name = NULL; - - dt_for_each_child_node(domain, node) - { - if ( dt_device_is_compatible(node, "multiboot,kernel") ) - { - u32 len; - const __be32 *val; - - val = dt_get_property(node, "reg", &len); - dt_get_range(&val, node, &kernel_addr, &size); - mod = boot_module_find_by_addr_and_kind( - BOOTMOD_KERNEL, kernel_addr); - info->kernel_bootmodule = mod; - } - else if ( dt_device_is_compatible(node, "multiboot,ramdisk") ) - { - u32 len; - const __be32 *val; - - val = dt_get_property(node, "reg", &len); - dt_get_range(&val, node, &initrd_addr, &size); - info->initrd_bootmodule = boot_module_find_by_addr_and_kind( - BOOTMOD_RAMDISK, initrd_addr); - } - else if ( dt_device_is_compatible(node, "multiboot,device-tree") ) - { - uint32_t len; - const __be32 *val; - - val = dt_get_property(node, "reg", &len); - if ( val == NULL ) - continue; - dt_get_range(&val, node, &dtb_addr, &size); - info->dtb_bootmodule = boot_module_find_by_addr_and_kind( - BOOTMOD_GUEST_DTB, dtb_addr); - } - else - continue; - } - name = dt_node_name(domain); - cmd = boot_cmdline_find_by_name(name); - if ( cmd ) - info->cmdline = &cmd->cmdline[0]; - } - if ( !mod || !mod->size ) - { - printk(XENLOG_ERR "Missing kernel boot module?\n"); - return -ENOENT; - } - - printk("Loading %pd kernel from boot module @ %"PRIpaddr"\n", - info->d, info->kernel_bootmodule->start); - if ( info->initrd_bootmodule ) - printk("Loading ramdisk from boot module @ %"PRIpaddr"\n", - info->initrd_bootmodule->start); - - /* - * uImage header always appears at the top of the image (even compressed), - * so it needs to be probed first. Note that in case of compressed uImage, - * kernel_decompress is called from kernel_uimage_probe making the function - * self-containing (i.e. fall through only in case of a header not found). - */ - rc = kernel_uimage_probe(info, mod); - if ( rc != -ENOENT ) - return rc; - - /* - * If it is a gzip'ed image, 32bit or 64bit, uncompress it. - * At this point, gzip header appears (if at all) at the top of the image, - * so pass 0 as an offset. - */ - rc = kernel_decompress(mod, 0); - if ( rc && rc != -EINVAL ) - return rc; - #ifdef CONFIG_ARM_64 - rc = kernel_zimage64_probe(info, mod->start, mod->size); + rc = kernel_zimage64_probe(info, addr, size); if (rc < 0) #endif - rc = kernel_zimage32_probe(info, mod->start, mod->size); + rc = kernel_zimage32_probe(info, addr, size); return rc; } -void __init kernel_load(struct kernel_info *info) -{ - info->load(info); -} - /* * Local variables: * mode: C diff --git a/xen/common/Kconfig b/xen/common/Kconfig index 099e6e72ad..83f8a8f791 100644 --- a/xen/common/Kconfig +++ b/xen/common/Kconfig @@ -14,13 +14,20 @@ config CORE_PARKING config DOM0LESS_BOOT bool "Dom0less boot support" if EXPERT - depends on ARM - default ARM + depends on DOMAIN_BUILD_HELPERS + default DOMAIN_BUILD_HELPERS help Dom0less boot support enables Xen to create and start domU guests during Xen boot without the need of a control domain (Dom0), which could be present anyway. +config DOMAIN_BUILD_HELPERS + bool + help + Introduce functions necessary for working with domain creation, kernel, + etc. As an examples, these type of functions are going to be used by + CONFIG_DOM0LESS_BOOT. + config GRANT_TABLE bool "Grant table support" if EXPERT default y diff --git a/xen/common/device-tree/Makefile b/xen/common/device-tree/Makefile index f3dafc9b81..e88a4d5799 100644 --- a/xen/common/device-tree/Makefile +++ b/xen/common/device-tree/Makefile @@ -4,3 +4,4 @@ obj-y += device-tree.o obj-$(CONFIG_DOM0LESS_BOOT) += dom0less-build.o obj-$(CONFIG_OVERLAY_DTB) += dt-overlay.o obj-y += intc.o +obj-$(CONFIG_DOMAIN_BUILD_HELPERS) += kernel.o diff --git a/xen/common/device-tree/kernel.c b/xen/common/device-tree/kernel.c new file mode 100644 index 0000000000..bd5d968bfd --- /dev/null +++ b/xen/common/device-tree/kernel.c @@ -0,0 +1,242 @@ +#include <xen/bootfdt.h> +#include <xen/device_tree.h> +#include <xen/errno.h> +#include <xen/gunzip.h> +#include <xen/init.h> +#include <xen/lib.h> +#include <xen/mm.h> +#include <xen/pfn.h> +#include <xen/sched.h> +#include <xen/types.h> +#include <xen/vmap.h> + +#include <asm/kernel.h> +#include <asm/page.h> +#include <asm/setup.h> + +static uint32_t __init output_length(char *image, unsigned long image_len) +{ + return *(uint32_t *)&image[image_len - 4]; +} + +int __init kernel_decompress(struct bootmodule *mod, uint32_t offset) +{ + char *output, *input; + char magic[2]; + int rc; + unsigned int kernel_order_out; + paddr_t output_size; + struct page_info *pages; + mfn_t mfn; + int i; + paddr_t addr = mod->start; + paddr_t size = mod->size; + + if ( size < offset ) + return -EINVAL; + + /* + * It might be that gzip header does not appear at the start address + * (e.g. in case of compressed uImage) so take into account offset to + * gzip header. + */ + addr += offset; + size -= offset; + + if ( size < 2 ) + return -EINVAL; + + copy_from_paddr(magic, addr, sizeof(magic)); + + /* only gzip is supported */ + if ( !gzip_check(magic, size) ) + return -EINVAL; + + input = ioremap_cache(addr, size); + if ( input == NULL ) + return -EFAULT; + + output_size = output_length(input, size); + kernel_order_out = get_order_from_bytes(output_size); + pages = alloc_domheap_pages(NULL, kernel_order_out, 0); + if ( pages == NULL ) + { + iounmap(input); + return -ENOMEM; + } + mfn = page_to_mfn(pages); + output = vmap_contig(mfn, 1 << kernel_order_out); + + rc = perform_gunzip(output, input, size); + clean_dcache_va_range(output, output_size); + iounmap(input); + vunmap(output); + + if ( rc ) + { + free_domheap_pages(pages, kernel_order_out); + return rc; + } + + mod->start = page_to_maddr(pages); + mod->size = output_size; + + /* + * Need to free pages after output_size here because they won't be + * freed by discard_initial_modules + */ + i = PFN_UP(output_size); + for ( ; i < (1 << kernel_order_out); i++ ) + free_domheap_page(pages + i); + + /* + * When using static heap feature, don't give bootmodules memory back to + * the heap allocator + */ + if ( using_static_heap ) + return 0; + + /* + * When freeing the kernel, we need to pass the module start address and + * size as they were before taking an offset to gzip header into account, + * so that the entire region will be freed. + */ + addr -= offset; + size += offset; + + /* + * Free the original kernel, update the pointers to the + * decompressed kernel + */ + fw_unreserved_regions(addr, addr + size, init_domheap_pages, 0); + + return 0; +} + +int __init kernel_probe(struct kernel_info *info, + const struct dt_device_node *domain) +{ + struct bootmodule *mod = NULL; + struct bootcmdline *cmd = NULL; + struct dt_device_node *node; + u64 kernel_addr, initrd_addr, dtb_addr, size; + int rc; + + /* + * We need to initialize start to 0. This field may be populated during + * kernel_xxx_probe() if the image has a fixed entry point (for e.g. + * uimage.ep). + * We will use this to determine if the image has a fixed entry point or + * the load address should be used as the start address. + */ + info->entry = 0; + + /* domain is NULL only for the hardware domain */ + if ( domain == NULL ) + { + ASSERT(is_hardware_domain(info->d)); + + mod = boot_module_find_by_kind(BOOTMOD_KERNEL); + + info->kernel_bootmodule = mod; + info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK); + + cmd = boot_cmdline_find_by_kind(BOOTMOD_KERNEL); + if ( cmd ) + info->cmdline = &cmd->cmdline[0]; + } + else + { + const char *name = NULL; + + dt_for_each_child_node(domain, node) + { + if ( dt_device_is_compatible(node, "multiboot,kernel") ) + { + u32 len; + const __be32 *val; + + val = dt_get_property(node, "reg", &len); + dt_get_range(&val, node, &kernel_addr, &size); + mod = boot_module_find_by_addr_and_kind( + BOOTMOD_KERNEL, kernel_addr); + info->kernel_bootmodule = mod; + } + else if ( dt_device_is_compatible(node, "multiboot,ramdisk") ) + { + u32 len; + const __be32 *val; + + val = dt_get_property(node, "reg", &len); + dt_get_range(&val, node, &initrd_addr, &size); + info->initrd_bootmodule = boot_module_find_by_addr_and_kind( + BOOTMOD_RAMDISK, initrd_addr); + } + else if ( dt_device_is_compatible(node, "multiboot,device-tree") ) + { + uint32_t len; + const __be32 *val; + + val = dt_get_property(node, "reg", &len); + if ( val == NULL ) + continue; + dt_get_range(&val, node, &dtb_addr, &size); + info->dtb_bootmodule = boot_module_find_by_addr_and_kind( + BOOTMOD_GUEST_DTB, dtb_addr); + } + else + continue; + } + name = dt_node_name(domain); + cmd = boot_cmdline_find_by_name(name); + if ( cmd ) + info->cmdline = &cmd->cmdline[0]; + } + if ( !mod || !mod->size ) + { + printk(XENLOG_ERR "Missing kernel boot module?\n"); + return -ENOENT; + } + + printk("Loading %pd kernel from boot module @ %"PRIpaddr"\n", + info->d, info->kernel_bootmodule->start); + if ( info->initrd_bootmodule ) + printk("Loading ramdisk from boot module @ %"PRIpaddr"\n", + info->initrd_bootmodule->start); + + /* + * uImage isn't really used nowadays thereby leave kernel_uimage_probe() + * call here just for compatability with Arm code. + */ +#ifdef CONFIG_ARM + /* + * uImage header always appears at the top of the image (even compressed), + * so it needs to be probed first. Note that in case of compressed uImage, + * kernel_decompress is called from kernel_uimage_probe making the function + * self-containing (i.e. fall through only in case of a header not found). + */ + rc = kernel_uimage_probe(info, mod); + if ( rc != -ENOENT ) + return rc; +#endif + + /* + * If it is a gzip'ed image, 32bit or 64bit, uncompress it. + * At this point, gzip header appears (if at all) at the top of the image, + * so pass 0 as an offset. + */ + rc = kernel_decompress(mod, 0); + if ( rc && rc != -EINVAL ) + return rc; + + rc = kernel_zimage_probe(info, mod->start, mod->size); + + return rc; +} + +void __init kernel_load(struct kernel_info *info) +{ + ASSERT(info && info->load); + + info->load(info); +} diff --git a/xen/include/asm-generic/kernel.h b/xen/include/asm-generic/kernel.h index b2bd04a185..d668c7ef4f 100644 --- a/xen/include/asm-generic/kernel.h +++ b/xen/include/asm-generic/kernel.h @@ -134,6 +134,19 @@ int kernel_probe(struct kernel_info *info, const struct dt_device_node *domain); */ void kernel_load(struct kernel_info *info); +int kernel_decompress(struct bootmodule *mod, uint32_t offset); + +int kernel_zimage_probe(struct kernel_info *info, paddr_t addr, paddr_t size); + +/* + * uImage isn't really used nowadays thereby leave kernel_uimage_probe() + * call here just for compatability with Arm code. + */ +#ifdef CONFIG_ARM +struct bootmodule; +int kernel_uimage_probe(struct kernel_info *info, struct bootmodule *mod); +#endif + #endif /*__ASM_GENERIC_KERNEL_H__ */ /* -- 2.47.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |