[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [MINI-OS PATCH 07/12] kexec: build parameters for new kernel
Build the parameters for the new kernel, consisting of the hvm_start_info struct, the memory map and the command line. Signed-off-by: Juergen Gross <jgross@xxxxxxxx> --- arch/x86/kexec.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ include/kexec.h | 4 ++++ kexec.c | 13 ++++++++++- 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/arch/x86/kexec.c b/arch/x86/kexec.c index 98a478d3..6fc7d02d 100644 --- a/arch/x86/kexec.c +++ b/arch/x86/kexec.c @@ -200,6 +200,7 @@ bool kexec_arch_need_analyze_shdrs(void) static unsigned long kexec_param_loc; static unsigned int kexec_param_size; +static unsigned long kexec_param_mem; void kexec_set_param_loc(const char *cmdline) { @@ -212,4 +213,61 @@ void kexec_set_param_loc(const char *cmdline) kexec_last_addr += kexec_param_size; kexec_last_addr = round_pgup(kexec_last_addr); } + +int kexec_get_entry(const char *cmdline) +{ + struct hvm_start_info *info; + struct hvm_memmap_table_entry *mmap; + unsigned int order; + unsigned int i; + + if ( kernel_entry == ~0UL ) + return ENOEXEC; + + order = get_order(kexec_param_size); + + kexec_param_mem = alloc_pages(order); + if ( !kexec_param_mem ) + return ENOMEM; + + info = (struct hvm_start_info *)kexec_param_mem; + memset(info, 0, sizeof(*info)); + info->magic = XEN_HVM_START_MAGIC_VALUE; + info->version = 1; + info->cmdline_paddr = kexec_param_mem + sizeof(*info) + + e820_entries * sizeof(struct hvm_memmap_table_entry); + info->memmap_paddr = kexec_param_mem + sizeof(*info); + info->memmap_entries = e820_entries; + + mmap = (struct hvm_memmap_table_entry *)(info + 1); + for ( i = 0; i < e820_entries; i++ ) + { + mmap->addr = e820_map[i].addr; + mmap->size = e820_map[i].size; + mmap->type = e820_map[i].type; + mmap++; + } + + strcpy((char *)mmap, cmdline); + + if ( kexec_add_action(KEXEC_COPY, to_virt(kexec_param_loc), info, + kexec_param_size) ) + return ENOSPC; + + /* The call of the new kernel happens via the physical address! */ + if ( kexec_add_action(KEXEC_CALL, (void *)kernel_entry, + (void *)kexec_param_loc, 0) ) + return ENOSPC; + + return 0; +} + +void kexec_get_entry_undo(void) +{ + if ( kexec_param_mem ) + { + free_pages((void *)kexec_param_mem, get_order(kexec_param_size)); + kexec_param_mem = 0; + } +} #endif /* CONFIG_KEXEC */ diff --git a/include/kexec.h b/include/kexec.h index 8a2b552f..7b103dea 100644 --- a/include/kexec.h +++ b/include/kexec.h @@ -45,4 +45,8 @@ bool kexec_arch_need_analyze_shdrs(void); /* Finalize parameter location and size. */ void kexec_set_param_loc(const char *cmdline); +/* Get entry point and parameter of new kernel. */ +int kexec_get_entry(const char *cmdline); +void kexec_get_entry_undo(void); + #endif /* _KEXEC_H */ diff --git a/kexec.c b/kexec.c index 68457711..0ef8eb35 100644 --- a/kexec.c +++ b/kexec.c @@ -177,10 +177,21 @@ int kexec(void *kernel, unsigned long kernel_size, const char *cmdline) reserve_memory_below(kexec_last_addr); + ret = kexec_get_entry(cmdline); + if ( ret ) + { + printk("kexec: ELF file of new kernel has no valid entry point\n"); + goto err; + } + /* Error exit. */ + ret = ENOSYS; + + err: unreserve_memory_below(); + kexec_get_entry_undo(); - return ENOSYS; + return ret; } EXPORT_SYMBOL(kexec); -- 2.43.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |