From: Cyrill Gorcunov <gorcunov@gmail.com>
To: Andi Kleen <ak@suse.de>
Cc: peterz@infradead.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH x86] [5/16] Replace hard coded reservations in x86-64 early boot code with dynamic table
Date: Fri, 4 Jan 2008 15:41:17 +0300 [thread overview]
Message-ID: <20080104124117.GE6310@cvg> (raw)
In-Reply-To: <20080103154218.F294E14DDB@wotan.suse.de>
[Andi Kleen - Thu, Jan 03, 2008 at 04:42:18PM +0100]
|
| On x86-64 there are several memory allocations before bootmem. To avoid
| them stomping on each other they used to be all hard coded in bad_area().
| Replace this with an array that is filled as needed.
|
| This cleans up the code considerably and allows to expand its use.
|
| Cc: peterz@infradead.org
|
| Signed-off-by: Andi Kleen <ak@suse.de>
|
| ---
| arch/x86/kernel/e820_64.c | 97 ++++++++++++++++++++++++---------------------
| arch/x86/kernel/head64.c | 48 ++++++++++++++++++++++
| arch/x86/kernel/setup_64.c | 67 +------------------------------
| arch/x86/mm/init_64.c | 5 +-
| arch/x86/mm/numa_64.c | 1
| include/asm-x86/e820_64.h | 5 +-
| include/asm-x86/proto.h | 2
| 7 files changed, 112 insertions(+), 113 deletions(-)
|
| Index: linux/arch/x86/kernel/e820_64.c
| ===================================================================
| --- linux.orig/arch/x86/kernel/e820_64.c
| +++ linux/arch/x86/kernel/e820_64.c
| @@ -47,56 +47,65 @@ unsigned long end_pfn_map;
| */
| static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT;
|
| -/* Check for some hardcoded bad areas that early boot is not allowed to touch */
| -static inline int bad_addr(unsigned long *addrp, unsigned long size)
| -{
| - unsigned long addr = *addrp, last = addr + size;
| +/*
| + * Early reserved memory areas.
| + */
| +#define MAX_EARLY_RES 20
|
| - /* various gunk below that needed for SMP startup */
| - if (addr < 0x8000) {
| - *addrp = PAGE_ALIGN(0x8000);
| - return 1;
| - }
| +struct early_res {
| + unsigned long start, end;
| +};
| +static struct early_res early_res[MAX_EARLY_RES] __initdata = {
| + { 0, PAGE_SIZE }, /* BIOS data page */
| +#ifdef CONFIG_SMP
| + { SMP_TRAMPOLINE_BASE, SMP_TRAMPOLINE_BASE + 2*PAGE_SIZE },
| +#endif
| + {}
| +};
|
| - /* direct mapping tables of the kernel */
| - if (last >= table_start<<PAGE_SHIFT && addr < table_end<<PAGE_SHIFT) {
| - *addrp = PAGE_ALIGN(table_end << PAGE_SHIFT);
| - return 1;
| +void __init reserve_early(unsigned long start, unsigned long end)
| +{
| + int i;
| + struct early_res *r;
| + for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
| + r = &early_res[i];
| + if (end > r->start && start < r->end)
| + panic("Duplicated early reservation %lx-%lx\n",
| + start, end);
| }
| + if (i >= MAX_EARLY_RES)
| + panic("Too many early reservations");
| + r = &early_res[i];
| + r->start = start;
| + r->end = end;
| +}
|
| - /* initrd */
| -#ifdef CONFIG_BLK_DEV_INITRD
| - if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
| - unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
| - unsigned long ramdisk_size = boot_params.hdr.ramdisk_size;
| - unsigned long ramdisk_end = ramdisk_image+ramdisk_size;
| +void __init early_res_to_bootmem(void)
| +{
| + int i;
| + for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
| + struct early_res *r = &early_res[i];
^^^^^^
---> just one tab used?
Andi, it seems that is a point Ingo complained about?
| + reserve_bootmem_generic(r->start, r->end - r->start);
| + }
| +}
|
| - if (last >= ramdisk_image && addr < ramdisk_end) {
| - *addrp = PAGE_ALIGN(ramdisk_end);
| - return 1;
| +/* Check for already reserved areas */
| +static inline int bad_addr(unsigned long *addrp, unsigned long size)
| +{
| + int i;
| + unsigned long addr = *addrp, last;
| + int changed = 0;
| +again:
| + last = addr + size;
| + for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
| + struct early_res *r = &early_res[i];
| + if (last >= r->start && addr < r->end) {
| + *addrp = addr = r->end;
| + changed = 1;
| + goto again;
| }
| - }
| -#endif
| - /* kernel code */
| - if (last >= __pa_symbol(&_text) && addr < __pa_symbol(&_end)) {
| - *addrp = PAGE_ALIGN(__pa_symbol(&_end));
| - return 1;
| - }
| -
| - if (last >= ebda_addr && addr < ebda_addr + ebda_size) {
| - *addrp = PAGE_ALIGN(ebda_addr + ebda_size);
| - return 1;
| - }
| -
| -#ifdef CONFIG_NUMA
| - /* NUMA memory to node map */
| - if (last >= nodemap_addr && addr < nodemap_addr + nodemap_size) {
| - *addrp = nodemap_addr + nodemap_size;
| - return 1;
| - }
| -#endif
| - /* XXX ramdisk image here? */
| - return 0;
| + }
| + return changed;
| }
|
| /*
| Index: linux/arch/x86/kernel/head64.c
| ===================================================================
| --- linux.orig/arch/x86/kernel/head64.c
| +++ linux/arch/x86/kernel/head64.c
| @@ -21,6 +21,7 @@
| #include <asm/tlbflush.h>
| #include <asm/sections.h>
| #include <asm/kdebug.h>
| +#include <asm/e820.h>
|
| static void __init zap_identity_mappings(void)
| {
| @@ -48,6 +49,35 @@ static void __init copy_bootdata(char *r
| }
| }
|
| +#define EBDA_ADDR_POINTER 0x40E
| +
| +static __init void reserve_ebda(void)
| +{
| + unsigned ebda_addr, ebda_size;
| +
| + /*
| + * there is a real-mode segmented pointer pointing to the
| + * 4K EBDA area at 0x40E
| + */
| + ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
| + ebda_addr <<= 4;
| +
| + if (!ebda_addr)
| + return;
| +
| + ebda_size = *(unsigned short *)__va(ebda_addr);
| +
| + /* Round EBDA up to pages */
| + if (ebda_size == 0)
| + ebda_size = 1;
| + ebda_size <<= 10;
| + ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
| + if (ebda_size > 64*1024)
| + ebda_size = 64*1024;
| +
| + reserve_early(ebda_addr, ebda_addr + ebda_size);
| +}
| +
| void __init x86_64_start_kernel(char * real_mode_data)
| {
| int i;
| @@ -70,5 +100,23 @@ void __init x86_64_start_kernel(char * r
| pda_init(0);
| copy_bootdata(__va(real_mode_data));
|
| + reserve_early(__pa_symbol(&_text), __pa_symbol(&_end));
| +
| + /* Reserve INITRD */
| + if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
| + unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
| + unsigned long ramdisk_size = boot_params.hdr.ramdisk_size;
| + unsigned long ramdisk_end = ramdisk_image + ramdisk_size;
| + reserve_early(ramdisk_image, ramdisk_end);
| + }
| +
| + reserve_ebda();
| +
| + /*
| + * At this point everything still needed from the boot loader
| + * or BIOS or kernel text should be early reserved or marked not
| + * RAM in e820. All other memory is free game.
| + */
| +
| start_kernel();
| }
| Index: linux/arch/x86/kernel/setup_64.c
| ===================================================================
| --- linux.orig/arch/x86/kernel/setup_64.c
| +++ linux/arch/x86/kernel/setup_64.c
| @@ -243,41 +243,6 @@ static inline void __init reserve_crashk
| {}
| #endif
|
| -#define EBDA_ADDR_POINTER 0x40E
| -
| -unsigned __initdata ebda_addr;
| -unsigned __initdata ebda_size;
| -
| -static void discover_ebda(void)
| -{
| - /*
| - * there is a real-mode segmented pointer pointing to the
| - * 4K EBDA area at 0x40E
| - */
| - ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
| - /*
| - * There can be some situations, like paravirtualized guests,
| - * in which there is no available ebda information. In such
| - * case, just skip it
| - */
| - if (!ebda_addr) {
| - ebda_size = 0;
| - return;
| - }
| -
| - ebda_addr <<= 4;
| -
| - ebda_size = *(unsigned short *)__va(ebda_addr);
| -
| - /* Round EBDA up to pages */
| - if (ebda_size == 0)
| - ebda_size = 1;
| - ebda_size <<= 10;
| - ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
| - if (ebda_size > 64*1024)
| - ebda_size = 64*1024;
| -}
| -
| /* Overridden in paravirt.c if CONFIG_PARAVIRT */
| void __attribute__((weak)) memory_setup(void)
| {
| @@ -355,8 +320,6 @@ void __init setup_arch(char **cmdline_p)
|
| check_efer();
|
| - discover_ebda();
| -
| init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
| if (efi_enabled)
| efi_init();
| @@ -399,33 +362,7 @@ void __init setup_arch(char **cmdline_p)
| contig_initmem_init(0, end_pfn);
| #endif
|
| - /* Reserve direct mapping */
| - reserve_bootmem_generic(table_start << PAGE_SHIFT,
| - (table_end - table_start) << PAGE_SHIFT);
| -
| - /* reserve kernel */
| - reserve_bootmem_generic(__pa_symbol(&_text),
| - __pa_symbol(&_end) - __pa_symbol(&_text));
| -
| - /*
| - * reserve physical page 0 - it's a special BIOS page on many boxes,
| - * enabling clean reboots, SMP operation, laptop functions.
| - */
| - reserve_bootmem_generic(0, PAGE_SIZE);
| -
| - /* reserve ebda region */
| - if (ebda_addr)
| - reserve_bootmem_generic(ebda_addr, ebda_size);
| -#ifdef CONFIG_NUMA
| - /* reserve nodemap region */
| - if (nodemap_addr)
| - reserve_bootmem_generic(nodemap_addr, nodemap_size);
| -#endif
| -
| -#ifdef CONFIG_SMP
| - /* Reserve SMP trampoline */
| - reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, 2*PAGE_SIZE);
| -#endif
| + early_res_to_bootmem();
|
| #ifdef CONFIG_ACPI_SLEEP
| /*
| @@ -455,6 +392,8 @@ void __init setup_arch(char **cmdline_p)
| initrd_start = ramdisk_image + PAGE_OFFSET;
| initrd_end = initrd_start+ramdisk_size;
| } else {
| + /* Assumes everything on node 0 */
| + free_bootmem(ramdisk_image, ramdisk_size);
| printk(KERN_ERR "initrd extends beyond end of memory "
| "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
| ramdisk_end, end_of_mem);
| Index: linux/arch/x86/mm/numa_64.c
| ===================================================================
| --- linux.orig/arch/x86/mm/numa_64.c
| +++ linux/arch/x86/mm/numa_64.c
| @@ -99,6 +99,7 @@ static int __init allocate_cachealigned_
| }
| pad_addr = (nodemap_addr + pad) & ~pad;
| memnodemap = phys_to_virt(pad_addr);
| + reserve_early(nodemap_addr, nodemap_addr + nodemap_size);
|
| printk(KERN_DEBUG "NUMA: Allocated memnodemap from %lx - %lx\n",
| nodemap_addr, nodemap_addr + nodemap_size);
| Index: linux/include/asm-x86/e820_64.h
| ===================================================================
| --- linux.orig/include/asm-x86/e820_64.h
| +++ linux/include/asm-x86/e820_64.h
| @@ -36,8 +36,9 @@ extern void finish_e820_parsing(void);
|
| extern struct e820map e820;
|
| -extern unsigned ebda_addr, ebda_size;
| -extern unsigned long nodemap_addr, nodemap_size;
| +extern void reserve_early(unsigned long start, unsigned long end);
| +extern void early_res_to_bootmem(void);
| +
| #endif/*!__ASSEMBLY__*/
|
| #endif/*__E820_HEADER*/
| Index: linux/arch/x86/mm/init_64.c
| ===================================================================
| --- linux.orig/arch/x86/mm/init_64.c
| +++ linux/arch/x86/mm/init_64.c
| @@ -176,7 +176,8 @@ __set_fixmap (enum fixed_addresses idx,
| set_pte_phys(address, phys, prot);
| }
|
| -unsigned long __meminitdata table_start, table_end;
| +static unsigned long __initdata table_start;
| +static unsigned long __meminitdata table_end;
|
| static __meminit void *alloc_low_page(unsigned long *phys)
| {
| @@ -387,6 +388,8 @@ void __init_refok init_memory_mapping(un
| if (!after_bootmem)
| mmu_cr4_features = read_cr4();
| __flush_tlb_all();
| +
| + reserve_early(table_start << PAGE_SHIFT, table_end << PAGE_SHIFT);
| }
|
| #ifndef CONFIG_NUMA
| Index: linux/include/asm-x86/proto.h
| ===================================================================
| --- linux.orig/include/asm-x86/proto.h
| +++ linux/include/asm-x86/proto.h
| @@ -22,8 +22,6 @@ extern void syscall32_cpu_init(void);
|
| extern void check_efer(void);
|
| -extern unsigned long table_start, table_end;
| -
| extern int reboot_force;
|
| long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
| --
| 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/
|
- Cyrill -
next prev parent reply other threads:[~2008-01-04 12:41 UTC|newest]
Thread overview: 103+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-03 15:42 [PATCH x86] [0/16] Various i386/x86-64 changes Andi Kleen
2008-01-03 15:42 ` [PATCH x86] [1/16] Make clocksource watchdog cycle through online CPUs Andi Kleen
2008-01-04 8:51 ` Ingo Molnar
2008-01-04 12:59 ` Andi Kleen
2008-01-03 15:42 ` [PATCH x86] [2/16] Add a counter for per cpu clocksource watchdog checks and report them in /proc/interrupts Andi Kleen
2008-01-04 8:53 ` Ingo Molnar
2008-01-03 15:42 ` [PATCH x86] [3/16] Turn irq debugging options into module params Andi Kleen
2008-01-04 8:55 ` Ingo Molnar
2008-01-03 15:42 ` [PATCH x86] [4/16] Add /proc/irq/*/spurious to dump the spurious irq debugging state Andi Kleen
2008-01-04 8:58 ` Ingo Molnar
2008-01-04 12:22 ` Andi Kleen
2008-01-03 15:42 ` [PATCH x86] [5/16] Replace hard coded reservations in x86-64 early boot code with dynamic table Andi Kleen
2008-01-04 9:00 ` Ingo Molnar
2008-01-04 12:23 ` Andi Kleen
2008-01-04 12:38 ` [PATCH x86] [5/16] Replace hard coded reservations in x86-64 early boot code with dynamic table II Andi Kleen
2008-01-04 14:41 ` Ingo Molnar
2008-01-04 15:03 ` Andi Kleen
2008-01-04 17:51 ` Sam Ravnborg
2008-01-04 18:06 ` Andi Kleen
2008-01-04 18:47 ` Joe Perches
2008-01-04 22:13 ` Andi Kleen
2008-01-04 22:46 ` J. Bruce Fields
2008-01-04 20:56 ` Sam Ravnborg
2008-01-04 12:41 ` Cyrill Gorcunov [this message]
2008-01-03 15:42 ` [PATCH x86] [6/16] Add a new arch_early_alloc() interface for x86-64 Andi Kleen
2008-01-03 16:22 ` Eric Dumazet
2008-01-03 17:17 ` Andi Kleen
2008-01-03 15:42 ` [PATCH x86] [7/16] Convert lockdep to use arch_early_alloc() if available for its large arrays Andi Kleen
2008-01-04 9:03 ` Ingo Molnar
2008-01-03 15:42 ` [PATCH x86] [8/16] Make lockdep_init __init Andi Kleen
2008-01-04 9:06 ` Ingo Molnar
2008-01-03 15:42 ` [PATCH x86] [9/16] Remove CPU capabitilites printks on i386 Andi Kleen
2008-01-04 9:11 ` Ingo Molnar
2008-01-03 15:42 ` [PATCH x86] [10/16] Document fdimage/isoimage completely in make help Andi Kleen
2008-01-04 9:00 ` Sam Ravnborg
2008-01-04 9:15 ` Ingo Molnar
2008-01-03 15:42 ` [PATCH x86] [11/16] Compile apm and voyager module only when selected in Kconfig Andi Kleen
2008-01-04 4:15 ` Stephen Rothwell
2008-01-03 15:42 ` [PATCH x86] [12/16] Optimize lock prefix switching to run less frequently Andi Kleen
2008-01-04 9:42 ` Thomas Gleixner
2008-01-04 12:17 ` Andi Kleen
2008-01-04 14:19 ` Thomas Gleixner
2008-01-04 14:39 ` Andi Kleen
2008-01-04 15:02 ` Pekka Enberg
2008-01-04 15:04 ` Andi Kleen
2008-01-04 20:34 ` Thomas Gleixner
2008-01-04 22:11 ` Andi Kleen
2008-01-05 1:19 ` Ingo Molnar
2008-01-05 14:37 ` Andi Kleen
2008-01-03 15:42 ` [PATCH x86] [13/16] i386: Set CFQ as default in i386 defconfig Andi Kleen
2008-01-04 9:19 ` Ingo Molnar
2008-01-03 15:42 ` [PATCH x86] [14/16] Enable RDC321X subarch only on 32bit Andi Kleen
2008-01-04 9:22 ` Ingo Molnar
2008-01-03 15:42 ` [PATCH x86] [15/16] Force __cpuinit on for CONFIG_PM without HOTPLUG_CPU Andi Kleen
2008-01-03 17:22 ` Rafael J. Wysocki
2008-01-03 17:42 ` Andi Kleen
2008-01-03 21:41 ` Rafael J. Wysocki
2008-01-04 9:23 ` Ingo Molnar
2008-01-10 17:14 ` Rafael J. Wysocki
2008-01-03 18:14 ` Adrian Bunk
2008-01-03 18:43 ` Andi Kleen
2008-01-10 9:54 ` Adrian Bunk
2008-01-10 9:58 ` Andi Kleen
2008-01-10 10:19 ` Adrian Bunk
2008-01-10 11:15 ` Andi Kleen
2008-01-10 11:26 ` Adrian Bunk
2008-01-10 11:42 ` Andi Kleen
2008-01-10 12:47 ` Adrian Bunk
2008-01-10 13:12 ` Andi Kleen
2008-01-10 15:09 ` Adrian Bunk
2008-01-14 13:52 ` Ingo Molnar
2008-01-14 14:09 ` Sam Ravnborg
2008-01-14 14:58 ` Ingo Molnar
2008-01-14 15:01 ` Ingo Molnar
2008-01-14 18:20 ` Adrian Bunk
2008-01-14 19:10 ` Ingo Molnar
2008-01-14 19:52 ` Adrian Bunk
2008-01-14 20:01 ` Sam Ravnborg
2008-01-14 20:18 ` Adrian Bunk
2008-01-14 20:27 ` Sam Ravnborg
2008-01-14 20:34 ` Adrian Bunk
2008-01-15 22:14 ` Ingo Molnar
2008-01-15 22:51 ` Adrian Bunk
2008-01-14 19:59 ` Sam Ravnborg
2008-01-15 22:12 ` [patch for v2.6.24] fix section mismatch warning in page_alloc.c Ingo Molnar
2008-01-14 15:05 ` [PATCH x86] [15/16] Force __cpuinit on for CONFIG_PM without HOTPLUG_CPU Ingo Molnar
2008-01-14 15:24 ` Ingo Molnar
2008-01-14 20:12 ` Sam Ravnborg
2008-01-15 15:17 ` Ingo Molnar
2008-01-15 16:25 ` Sam Ravnborg
2008-01-15 17:11 ` Andi Kleen
2008-01-15 17:27 ` Adrian Bunk
2008-01-15 18:21 ` Sam Ravnborg
2008-01-15 18:29 ` Andi Kleen
2008-01-15 18:31 ` Sam Ravnborg
2008-01-15 18:47 ` Adrian Bunk
2008-01-14 18:17 ` Adrian Bunk
2008-01-14 15:25 ` Adrian Bunk
2008-01-10 17:17 ` Rafael J. Wysocki
2008-01-11 23:06 ` [PATCH] x86: Change unnecessary dependencies on CONFIG_PM Rafael J. Wysocki
2008-01-03 15:42 ` [PATCH x86] [16/16] Mark memory_setup __init Andi Kleen
2008-01-04 9:25 ` Ingo Molnar
2008-01-04 9:53 ` Ingo Molnar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080104124117.GE6310@cvg \
--to=gorcunov@gmail.com \
--cc=ak@suse.de \
--cc=linux-kernel@vger.kernel.org \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox