Messages in this thread Patch in this message | | | Subject | [PATCH -mm -v4 1/3] i386/x86_64 boot: setup data | From | "Huang, Ying" <> | Date | Tue, 09 Oct 2007 14:40:10 +0800 |
| |
This patch add a field of 64-bit physical pointer to NULL terminated single linked list of struct setup_data to real-mode kernel header. This is used as a more extensible boot parameters passing mechanism.
Signed-off-by: Huang Ying <ying.huang@intel.com>
---
arch/i386/Kconfig | 3 - arch/i386/boot/header.S | 8 +++ arch/i386/kernel/setup.c | 92 +++++++++++++++++++++++++++++++++++++++++++ arch/x86_64/kernel/setup.c | 37 +++++++++++++++++ include/asm-i386/bootparam.h | 15 +++++++ include/asm-i386/io.h | 7 +++ include/linux/mm.h | 2 mm/memory.c | 24 +++++++++++ 8 files changed, 184 insertions(+), 4 deletions(-)
Index: linux-2.6.23-rc8/include/asm-i386/bootparam.h =================================================================== --- linux-2.6.23-rc8.orig/include/asm-i386/bootparam.h 2007-10-09 11:26:06.000000000 +0800 +++ linux-2.6.23-rc8/include/asm-i386/bootparam.h 2007-10-09 14:15:14.000000000 +0800 @@ -9,6 +9,17 @@ #include <asm/ist.h> #include <video/edid.h> +/* setup data types */ +#define SETUP_NONE 0 + +/* extensible setup data list node */ +struct setup_data { + u64 next; + u32 type; + u32 len; + u8 data[0]; +} __attribute__((packed)); + struct setup_header { u8 setup_sects; u16 root_flags; @@ -41,6 +52,10 @@ u32 initrd_addr_max; u32 kernel_alignment; u8 relocatable_kernel; + u8 _pad2[3]; + u32 cmdline_size; + u32 _pad3; + u64 setup_data; } __attribute__((packed)); struct sys_desc_table { Index: linux-2.6.23-rc8/arch/i386/boot/header.S =================================================================== --- linux-2.6.23-rc8.orig/arch/i386/boot/header.S 2007-10-09 11:26:06.000000000 +0800 +++ linux-2.6.23-rc8/arch/i386/boot/header.S 2007-10-09 11:26:08.000000000 +0800 @@ -119,7 +119,7 @@ # Part 2 of the header, from the old setup.S .ascii "HdrS" # header signature - .word 0x0206 # header version number (>= 0x0105) + .word 0x0207 # header version number (>= 0x0105) # or else old loadlin-1.5 will fail) .globl realmode_swtch realmode_swtch: .word 0, 0 # default_switch, SETUPSEG @@ -214,6 +214,12 @@ #added with boot protocol #version 2.06 +pad4: .long 0 + +setup_data: .quad 0 # 64-bit physical pointer to + # single linked list of + # struct setup_data + # End of setup header ##################################################### .section ".inittext", "ax" Index: linux-2.6.23-rc8/arch/x86_64/kernel/setup.c =================================================================== --- linux-2.6.23-rc8.orig/arch/x86_64/kernel/setup.c 2007-10-09 11:26:06.000000000 +0800 +++ linux-2.6.23-rc8/arch/x86_64/kernel/setup.c 2007-10-09 14:15:14.000000000 +0800 @@ -250,6 +250,40 @@ ebda_size = 64*1024; } +static void __init parse_setup_data(void) +{ + struct setup_data *data; + unsigned long pa_data; + + if (boot_params.hdr.version < 0x0207) + return; + pa_data = boot_params.hdr.setup_data; + while (pa_data) { + data = early_ioremap(pa_data, PAGE_SIZE); + switch (data->type) { + default: + break; + } + pa_data = data->next; + early_iounmap(data, PAGE_SIZE); + } +} + +static void __init reserve_setup_data(void) +{ + struct setup_data *data; + unsigned long pa_data; + + if (boot_params.hdr.version < 0x0207) + return; + pa_data = boot_params.hdr.setup_data; + while (pa_data) { + data = __va(pa_data); + reserve_bootmem_generic(pa_data, sizeof(*data)+data->len); + pa_data = data->next; + } +} + void __init setup_arch(char **cmdline_p) { printk(KERN_INFO "Command line: %s\n", boot_command_line); @@ -285,6 +319,8 @@ strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; + parse_setup_data(); + parse_early_param(); finish_e820_parsing(); @@ -373,6 +409,7 @@ */ acpi_reserve_bootmem(); #endif + reserve_setup_data(); /* * Find and reserve possible boot-time SMP configuration: */ Index: linux-2.6.23-rc8/arch/i386/kernel/setup.c =================================================================== --- linux-2.6.23-rc8.orig/arch/i386/kernel/setup.c 2007-10-09 11:26:06.000000000 +0800 +++ linux-2.6.23-rc8/arch/i386/kernel/setup.c 2007-10-09 14:20:04.000000000 +0800 @@ -424,6 +424,91 @@ {} #endif +static void __init reserve_setup_data(void) +{ + struct setup_data *data; + unsigned long max_low_addr = (max_low_pfn<<PAGE_SHIFT); + unsigned long pa_data, data_len; + + if (boot_params.hdr.version < 0x0207) + return; + pa_data = boot_params.hdr.setup_data; + while (pa_data) { + data = boot_ioremap(pa_data, sizeof(*data)); + data_len = sizeof(*data)+data->len; + if (pa_data+data_len <= max_low_addr) + reserve_bootmem(pa_data, data_len); + else if (pa_data < max_low_addr) + reserve_bootmem(pa_data, max_low_addr - pa_data); + pa_data = data->next; + } +} + +/* + * The setup data in high memory can not be reserved by bootmem + * allocator, so they are copied to low memory. + */ +static void __init copy_setup_data(void) +{ + struct setup_data data, *pdata; + u64 *ppa_next; + unsigned long data_len; + + if (boot_params.hdr.version < 0x0207) + return; + ppa_next = &boot_params.hdr.setup_data; + while (*ppa_next) { + copy_from_phys(&data, *ppa_next, sizeof(data)); + data_len = sizeof(data)+data.len; + if (*ppa_next+data_len > (max_low_pfn<<PAGE_SHIFT)) { + pdata = alloc_bootmem_low(data_len); + copy_from_phys(pdata, *ppa_next, data_len); + *ppa_next = __pa(pdata); + } + ppa_next = &((struct setup_data *)__va(*ppa_next))->next; + } +} + +static void __init parse_setup_data(void) +{ + struct setup_data *data; + unsigned long pa_data, pa_next; + + if (boot_params.hdr.version < 0x0207) + return; + pa_data = boot_params.hdr.setup_data; + while (pa_data) { + data = boot_ioremap(pa_data, PAGE_SIZE); + pa_next = data->next; + switch (data->type) { + default: + break; + } + pa_data = pa_next; + } +} + +/* + * The memory location of setup data may be changed after + * copy_setup_data, so late_parse_setup_data are provided for needed + * user. + */ +static void __init late_parse_setup_data(void) +{ + struct setup_data *data; + + if (boot_params.hdr.version < 0x0207) + return; + for (data = __va(boot_params.hdr.setup_data); + data != __va(0); + data = __va(data->next)) { + switch (data->type) { + default: + break; + } + } +} + void __init setup_bootmem_allocator(void) { unsigned long bootmap_size; @@ -500,6 +585,7 @@ } #endif reserve_crashkernel(); + reserve_setup_data(); } /* @@ -583,6 +669,9 @@ rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0); rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0); #endif + + parse_setup_data(); + ARCH_SETUP if (efi_enabled) efi_init(); @@ -657,6 +746,9 @@ if (efi_enabled) efi_map_memmap(); + copy_setup_data(); + late_parse_setup_data(); + #ifdef CONFIG_ACPI /* * Parse the ACPI tables for possible boot-time SMP configuration. Index: linux-2.6.23-rc8/include/asm-i386/io.h =================================================================== --- linux-2.6.23-rc8.orig/include/asm-i386/io.h 2007-10-09 11:26:06.000000000 +0800 +++ linux-2.6.23-rc8/include/asm-i386/io.h 2007-10-09 11:26:08.000000000 +0800 @@ -126,6 +126,13 @@ extern void iounmap(volatile void __iomem *addr); /* + * boot_ioremap is for temporary early boot-time mappings, before + * paging_init(), when the boot-time page tables are still in use. + * The mapping is currently limited to at most 4 pages. + */ +extern void *boot_ioremap(unsigned long offset, unsigned long size); + +/* * bt_ioremap() and bt_iounmap() are for temporary early boot-time * mappings, before the real ioremap() is functional. * A boot-time mapping is currently limited to at most 16 pages. Index: linux-2.6.23-rc8/arch/i386/Kconfig =================================================================== --- linux-2.6.23-rc8.orig/arch/i386/Kconfig 2007-10-09 11:26:06.000000000 +0800 +++ linux-2.6.23-rc8/arch/i386/Kconfig 2007-10-09 11:26:08.000000000 +0800 @@ -784,11 +784,8 @@ The default yes will allow the kernel to do irq load balancing. Saying no will keep the kernel from doing irq load balancing. -# turning this on wastes a bunch of space. -# Summit needs it only when NUMA is on config BOOT_IOREMAP bool - depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI)) default y config SECCOMP Index: linux-2.6.23-rc8/include/linux/mm.h =================================================================== --- linux-2.6.23-rc8.orig/include/linux/mm.h 2007-10-09 11:26:06.000000000 +0800 +++ linux-2.6.23-rc8/include/linux/mm.h 2007-10-09 11:26:08.000000000 +0800 @@ -942,6 +942,8 @@ extern void show_mem(void); extern void si_meminfo(struct sysinfo * val); extern void si_meminfo_node(struct sysinfo *val, int nid); +extern unsigned long copy_from_phys(void *to, unsigned long from_phys, + unsigned long n); #ifdef CONFIG_NUMA extern void setup_per_cpu_pageset(void); Index: linux-2.6.23-rc8/mm/memory.c =================================================================== --- linux-2.6.23-rc8.orig/mm/memory.c 2007-10-09 11:26:06.000000000 +0800 +++ linux-2.6.23-rc8/mm/memory.c 2007-10-09 11:26:08.000000000 +0800 @@ -2788,3 +2788,27 @@ return buf - old_buf; } EXPORT_SYMBOL_GPL(access_process_vm); + +unsigned long copy_from_phys(void *to, unsigned long from_phys, + unsigned long n) +{ + struct page *page; + void *from; + unsigned long remain = n, offset, trunck; + + while (remain) { + page = pfn_to_page(from_phys >> PAGE_SHIFT); + from = kmap_atomic(page, KM_USER0); + offset = from_phys & ~PAGE_MASK; + if (remain > PAGE_SIZE - offset) + trunck = PAGE_SIZE - offset; + else + trunck = remain; + memcpy(to, from + offset, trunck); + kunmap_atomic(from, KM_USER0); + to += trunck; + from_phys += trunck; + remain -= trunck; + } + return n; +} - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |