Hello,
I have this chain: coreboot v2 -> etherboot as the payload -> x86_64 kernel 2.6.25.6.
The kernel panics in arch/x86/e820_64.c, reserve_early() with the message:
Overlapping early reservations f0-100ef EBDA to 0-fff BIOS data page
reserve_early(start,end) is called from arch/x86/head64.c, reserve_ebda() with start=0xf0 and end=0x100f0.
The address and size of EBDA is gotten this way:
#define EBDA_ADDR_POINTER 0x40E ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER); ebda_addr <<= 4; ebda_size = *(unsigned short *)__va(ebda_addr);
After the above sequence ebda_addr=0xf0 and ebda_size=0x2049 KiB;
This all happened in a very well working system after I added the second dual-core Opteron.
Without the second CPU, ebda_addr=0x12010 and ebda_size=0, which combination passes reserve_early() without overlapping. The resulting reservations are: early res: 0 [0-fff] BIOS data page early res: 1 [6000-7fff] SMP_TRAMPOLINE early res: 2 [200000-75b503] TEXT DATA BSS early res: 3 [800000-9bd8dd] RAMDISK early res: 4 [12010-1300f] EBDA early res: 5 [8000-cfff] PGTABLE
How come? What is responsible to clear the memory at 0x40e? What is EBDA and what needs it?
Thanks, Roman Kononov
On Mon, Jul 21, 2008 at 2:27 PM, Roman Kononov kononov@dls.net wrote:
Hello,
I have this chain: coreboot v2 -> etherboot as the payload -> x86_64 kernel 2.6.25.6.
The kernel panics in arch/x86/e820_64.c, reserve_early() with the message:
Overlapping early reservations f0-100ef EBDA to 0-fff BIOS data page
reserve_early(start,end) is called from arch/x86/head64.c, reserve_ebda() with start=0xf0 and end=0x100f0.
The address and size of EBDA is gotten this way:
#define EBDA_ADDR_POINTER 0x40E ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER); ebda_addr <<= 4; ebda_size = *(unsigned short *)__va(ebda_addr);
After the above sequence ebda_addr=0xf0 and ebda_size=0x2049 KiB;
This all happened in a very well working system after I added the second dual-core Opteron.
Without the second CPU, ebda_addr=0x12010 and ebda_size=0, which combination passes reserve_early() without overlapping. The resulting reservations are: early res: 0 [0-fff] BIOS data page early res: 1 [6000-7fff] SMP_TRAMPOLINE early res: 2 [200000-75b503] TEXT DATA BSS early res: 3 [800000-9bd8dd] RAMDISK early res: 4 [12010-1300f] EBDA early res: 5 [8000-cfff] PGTABLE
How come? What is responsible to clear the memory at 0x40e? What is EBDA and what needs it?
interesting, EBDA should be in [0x90000, 0x100000]
please check with 2.6.26
YH
On Mon, Jul 21, 2008 at 2:52 PM, yhlu yinghailu@gmail.com wrote:
On Mon, Jul 21, 2008 at 2:27 PM, Roman Kononov kononov@dls.net wrote:
Hello,
I have this chain: coreboot v2 -> etherboot as the payload -> x86_64 kernel 2.6.25.6.
The kernel panics in arch/x86/e820_64.c, reserve_early() with the message:
Overlapping early reservations f0-100ef EBDA to 0-fff BIOS data page
reserve_early(start,end) is called from arch/x86/head64.c, reserve_ebda() with start=0xf0 and end=0x100f0.
The address and size of EBDA is gotten this way:
#define EBDA_ADDR_POINTER 0x40E ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER); ebda_addr <<= 4; ebda_size = *(unsigned short *)__va(ebda_addr);
After the above sequence ebda_addr=0xf0 and ebda_size=0x2049 KiB;
This all happened in a very well working system after I added the second dual-core Opteron.
Without the second CPU, ebda_addr=0x12010 and ebda_size=0, which combination passes reserve_early() without overlapping. The resulting reservations are: early res: 0 [0-fff] BIOS data page early res: 1 [6000-7fff] SMP_TRAMPOLINE early res: 2 [200000-75b503] TEXT DATA BSS early res: 3 [800000-9bd8dd] RAMDISK early res: 4 [12010-1300f] EBDA early res: 5 [8000-cfff] PGTABLE
How come? What is responsible to clear the memory at 0x40e? What is EBDA and what needs it?
interesting, EBDA should be in [0x90000, 0x100000]
linuxbios doesn't honor the 0x40e, and will use first 4k for irq table etc.
please try to update write_tables like..
/* 2006.1 yhlu add mptable cross 0x467 processing */
#include <console/console.h> #include <cpu/cpu.h> #include <boot/tables.h> #include <boot/linuxbios_tables.h> #include <arch/pirq_routing.h> #include <arch/smp/mpspec.h> #include <arch/acpi.h> #include "linuxbios_table.h"
struct lb_memory *write_tables(void) { unsigned long low_table_start, low_table_end, new_low_table_end; unsigned long rom_table_start, rom_table_end;
rom_table_start = 0xf0000; rom_table_end = 0xf0000; /* Start low addr at 16 bytes instead of 0 because of a buglet * in the generic linux unzip code, as it tests for the a20 line. */ low_table_start = 0; low_table_end = 16;
post_code(0x9a);
/* This table must be betweeen 0xf0000 & 0x100000 */ rom_table_end = write_pirq_routing_table(rom_table_end); rom_table_end = (rom_table_end + 1023) & ~1023;
/* Write ACPI tables */ /* write them in the rom area because DSDT can be large (8K on epia-m) which * pushes linuxbios table out of first 4K if set up in low table area */ rom_table_end = write_acpi_tables(rom_table_end); rom_table_end = (rom_table_end+1023) & ~1023;
/* copy the smp block to address 0 */ post_code(0x96);
/* The smp table must be in 0-1K, 639K-640K, or 960K-1M */ new_low_table_end = write_smp_table(low_table_end); // low_table_end is 0x10 at this point
#if HAVE_MP_TABLE /* Don't write anything in the traditional x86 BIOS data segment, * for example the linux kernel smp need to use 0x467 to pass reset vector * or use 0x40e/0x413 for EBDA finding... */ if(new_low_table_end>0x400){ unsigned mptable_size; unsigned mpc_start; low_table_end += SMP_FLOATING_TABLE_LEN; /* keep the mpf in 1k low, so kernel can find it */ mptable_size = new_low_table_end - low_table_end; /* We can not put mptable low, we need to copy them to somewhere else*/ if((rom_table_end+mptable_size)<0x100000) { /* We can copy mptable on rom_table */ mpc_start = rom_table_end; rom_table_end += mptable_size; rom_table_end = (rom_table_end+1023) & ~1023; } else { /* We can need to put mptable before rom_table */ mpc_start = rom_table_start - mptable_size; mpc_start &= ~1023; rom_table_start = mpc_start; } printk_debug("move mptable from 0x%0x to 0x%0x, size 0x%0x\n", low_table_end, mpc_start, mptable_size); memcpy((unsigned char *)mpc_start, (unsigned char *)low_table_end, mptable_size); smp_write_floating_table_physaddr(low_table_end - SMP_FLOATING_TABLE_LEN, mpc_start); memset((unsigned char *)low_table_end, '\0', mptable_size); } #endif if(low_table_end<0x500) { low_table_end = 0x500; }
/* The linuxbios table must be in 0-4K or 960K-1M */ write_linuxbios_table(low_table_start, low_table_end, rom_table_start, rom_table_end);
return get_lb_mem(); }
On Mon, Jul 21, 2008 at 3:16 PM, yhlu yinghailu@gmail.com wrote:
On Mon, Jul 21, 2008 at 2:52 PM, yhlu yinghailu@gmail.com wrote:
On Mon, Jul 21, 2008 at 2:27 PM, Roman Kononov kononov@dls.net wrote:
Hello,
I have this chain: coreboot v2 -> etherboot as the payload -> x86_64 kernel 2.6.25.6.
The kernel panics in arch/x86/e820_64.c, reserve_early() with the message:
Overlapping early reservations f0-100ef EBDA to 0-fff BIOS data page
reserve_early(start,end) is called from arch/x86/head64.c, reserve_ebda() with start=0xf0 and end=0x100f0.
The address and size of EBDA is gotten this way:
#define EBDA_ADDR_POINTER 0x40E ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER); ebda_addr <<= 4; ebda_size = *(unsigned short *)__va(ebda_addr);
After the above sequence ebda_addr=0xf0 and ebda_size=0x2049 KiB;
This all happened in a very well working system after I added the second dual-core Opteron.
Without the second CPU, ebda_addr=0x12010 and ebda_size=0, which combination passes reserve_early() without overlapping. The resulting reservations are: early res: 0 [0-fff] BIOS data page early res: 1 [6000-7fff] SMP_TRAMPOLINE early res: 2 [200000-75b503] TEXT DATA BSS early res: 3 [800000-9bd8dd] RAMDISK early res: 4 [12010-1300f] EBDA early res: 5 [8000-cfff] PGTABLE
How come? What is responsible to clear the memory at 0x40e? What is EBDA and what needs it?
interesting, EBDA should be in [0x90000, 0x100000]
linuxbios doesn't honor the 0x40e, and will use first 4k for irq table etc.
please try to update write_tables like..
/* 2006.1 yhlu add mptable cross 0x467 processing */
#include <console/console.h> #include <cpu/cpu.h> #include <boot/tables.h> #include <boot/linuxbios_tables.h> #include <arch/pirq_routing.h> #include <arch/smp/mpspec.h> #include <arch/acpi.h> #include "linuxbios_table.h"
struct lb_memory *write_tables(void) { unsigned long low_table_start, low_table_end, new_low_table_end; unsigned long rom_table_start, rom_table_end;
rom_table_start = 0xf0000; rom_table_end = 0xf0000; /* Start low addr at 16 bytes instead of 0 because of a buglet * in the generic linux unzip code, as it tests for the a20 line. */ low_table_start = 0; low_table_end = 16; post_code(0x9a); /* This table must be betweeen 0xf0000 & 0x100000 */ rom_table_end = write_pirq_routing_table(rom_table_end); rom_table_end = (rom_table_end + 1023) & ~1023; /* Write ACPI tables */ /* write them in the rom area because DSDT can be large (8K on
epia-m) which * pushes linuxbios table out of first 4K if set up in low table area */ rom_table_end = write_acpi_tables(rom_table_end); rom_table_end = (rom_table_end+1023) & ~1023;
/* copy the smp block to address 0 */ post_code(0x96); /* The smp table must be in 0-1K, 639K-640K, or 960K-1M */ new_low_table_end = write_smp_table(low_table_end); //
low_table_end is 0x10 at this point
#if HAVE_MP_TABLE /* Don't write anything in the traditional x86 BIOS data segment, * for example the linux kernel smp need to use 0x467 to pass reset vector * or use 0x40e/0x413 for EBDA finding... */ if(new_low_table_end>0x400){ unsigned mptable_size; unsigned mpc_start; low_table_end += SMP_FLOATING_TABLE_LEN; /* keep the mpf in 1k low, so kernel can find it */ mptable_size = new_low_table_end - low_table_end; /* We can not put mptable low, we need to copy them to somewhere else*/ if((rom_table_end+mptable_size)<0x100000) { /* We can copy mptable on rom_table */ mpc_start = rom_table_end; rom_table_end += mptable_size; rom_table_end = (rom_table_end+1023) & ~1023; } else { /* We can need to put mptable before rom_table */ mpc_start = rom_table_start - mptable_size; mpc_start &= ~1023; rom_table_start = mpc_start; } printk_debug("move mptable from 0x%0x to 0x%0x, size 0x%0x\n", low_table_end, mpc_start, mptable_size); memcpy((unsigned char *)mpc_start, (unsigned char *)low_table_end, mptable_size); smp_write_floating_table_physaddr(low_table_end - SMP_FLOATING_TABLE_LEN, mpc_start); memset((unsigned char *)low_table_end, '\0', mptable_size); } #endif if(low_table_end<0x500) { low_table_end = 0x500; }
/* The linuxbios table must be in 0-4K or 960K-1M */ write_linuxbios_table(low_table_start, low_table_end, rom_table_start, rom_table_end); return get_lb_mem();
}
and
unsigned long write_linuxbios_table( unsigned long low_table_start, unsigned long low_table_end, unsigned long rom_table_start, unsigned long rom_table_end) { unsigned long table_size; struct lb_header *head; struct lb_memory *mem;
if(low_table_end > (0x1000 - sizeof(struct lb_header))) { /* after 4K */ /* We need to put lbtable on to [0xf0000,0x100000) */ head = lb_table_init(rom_table_end); rom_table_end = (unsigned long)head; } else { head = lb_table_init(low_table_end); low_table_end = (unsigned long)head; }
printk_debug("Adjust low_table_end from 0x%08x to ", low_table_end); low_table_end += 0xfff; // 4K align low_table_end &= ~0xfff; printk_debug("0x%08x \n", low_table_end); /* kernel assume this position is reserved */ printk_debug("Adjust rom_table_end from 0x%08x to ", rom_table_end); rom_table_end += 0xffff; // 64K align rom_table_end &= ~0xffff; printk_debug("0x%08x \n", rom_table_end);
if (HAVE_OPTION_TABLE == 1) { struct lb_record *rec_dest, *rec_src; /* Write the option config table... */ rec_dest = lb_new_record(head); rec_src = (struct lb_record *)(void *)&option_table; memcpy(rec_dest, rec_src, rec_src->size); /* Create cmos checksum entry in linuxbios table */ lb_cmos_checksum(head); } /* Record where RAM is located */ mem = build_lb_mem(head);
/* Record the mptable and the the lb_table (This will be adjusted later) */ lb_add_memory_range(mem, LB_MEM_TABLE, low_table_start, low_table_end - low_table_start);
/* Record the pirq table, acpi tables, and maybe the mptable */ lb_add_memory_range(mem, LB_MEM_TABLE, rom_table_start, rom_table_end - rom_table_start);
/* Note: * I assume that there is always memory at immediately after * the low_table_end. This means that after I setup the linuxbios table. * I can trivially fixup the reserved memory ranges to hold the correct * size of the linuxbios table. */
/* Record our motheboard */ lb_mainboard(head); /* Record our various random string information */ lb_strings(head);
/* Remember where my valid memory ranges are */ return lb_table_fini(head);
}
This patch fixes the EBDA mislocation problem. Thank you, Yinghai.
The change in coreboot_table.c is not strictly necessary. It removes some redundancy and confusion.
The change in tables.c protects the legacy x86 BIOS data segment (0x400-0x4ff) from being used for storing coreboot tables. Some bytes from the segment are used by the kernel and should not be garbled.
Signed-off-by: Roman Kononov kononov@dls.net
Roman Kononov wrote:
This patch fixes the EBDA mislocation problem. Thank you, Yinghai.
The change in coreboot_table.c is not strictly necessary. It removes some redundancy and confusion.
The change in tables.c protects the legacy x86 BIOS data segment (0x400-0x4ff) from being used for storing coreboot tables. Some bytes from the segment are used by the kernel and should not be garbled.
Signed-off-by: Roman Kononov kononov@dls.net
Wow, I am surprised we didn't see this failure sooner. I guess we were lucky.
Acked-by: Marc Jones marc.jones@amd.com
r3437
On Wed, Jul 23, 2008 at 4:23 PM, Marc Jones Marc.Jones@amd.com wrote:
Roman Kononov wrote:
This patch fixes the EBDA mislocation problem. Thank you, Yinghai.
The change in coreboot_table.c is not strictly necessary. It removes some redundancy and confusion.
The change in tables.c protects the legacy x86 BIOS data segment (0x400-0x4ff) from being used for storing coreboot tables. Some bytes from the segment are used by the kernel and should not be garbled.
Signed-off-by: Roman Kononov kononov@dls.net
Wow, I am surprised we didn't see this failure sooner. I guess we were lucky.
128 cpus on simNow....because mptable is some big to overwrite 0x467...
YH