[coreboot] kernel panics reserving EBDA pages

yhlu yinghailu at gmail.com
Tue Jul 22 00:16:51 CEST 2008


On Mon, Jul 21, 2008 at 2:52 PM, yhlu <yinghailu at gmail.com> wrote:
> On Mon, Jul 21, 2008 at 2:27 PM, Roman Kononov <kononov at 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();
}




More information about the coreboot mailing list