Mike Loptien (mike.loptien@se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5978
-gerrit
commit c94b08693265810496e8354a199bc07e03a2bdb3 Author: Mike Loptien mike.loptien@se-eng.com Date: Wed Jun 11 14:26:10 2014 -0600
MP Spec: Add debugging capabilities
The MP Table did not have any sort of debug capabilities like the ACPI and SMBIOS tables do. If both BIOS_SPEW or BIOS_DEBUG and CONFIG_DEBUG_MP_TABLE are selected, this will print out all of the tables that get created by the MP Table process.
Change-Id: I13a446043c5094a680eb7461ec4b61427b7a7050 Signed-off-by: Mike Loptien mike.loptien@se-eng.com --- src/Kconfig | 14 ++ src/arch/x86/boot/mpspec.c | 275 ++++++++++++++++++++++++++++++++- src/arch/x86/include/arch/smp/mpspec.h | 2 + 3 files changed, 283 insertions(+), 8 deletions(-)
diff --git a/src/Kconfig b/src/Kconfig index 061f63e..1252b03 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -842,6 +842,20 @@ config DEBUG_ACPI
# Only visible if debug level is DEBUG (7) or SPEW (8) as it does additional # printk(BIOS_DEBUG, ...) calls. +config DEBUG_MP_TABLE + prompt "Output verbose MP Table debug messages" if DEFAULT_CONSOLE_LOGLEVEL_7 || DEFAULT_CONSOLE_LOGLEVEL_8 + bool + default n + depends on HAVE_MP_TABLE + help + This option enables additional MP Table related debug messages. + + Note: This option will slightly increase the size of the coreboot image. + + If unsure, say N. + +# Only visible if debug level is DEBUG (7) or SPEW (8) as it does additional +# printk(BIOS_DEBUG, ...) calls. config REALMODE_DEBUG prompt "Enable debug messages for option ROM execution" if DEFAULT_CONSOLE_LOGLEVEL_7 || DEFAULT_CONSOLE_LOGLEVEL_8 bool diff --git a/src/arch/x86/boot/mpspec.c b/src/arch/x86/boot/mpspec.c index d079d08..d27ed4f 100644 --- a/src/arch/x86/boot/mpspec.c +++ b/src/arch/x86/boot/mpspec.c @@ -27,6 +27,10 @@ #include <cpu/x86/lapic.h> #include <drivers/generic/ioapic/chip.h>
+#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) +#include <lib.h> /* hexdump */ +#endif + /* Initialize the specified "mc" struct with initial values. */ void mptable_init(struct mp_config_table *mc, u32 lapic_addr) { @@ -58,6 +62,25 @@ void mptable_init(struct mp_config_table *mc, u32 lapic_addr) mc->mpc_oem[i] = ' '; for (i = MIN(strlen(CONFIG_MAINBOARD_PART_NUMBER), 12); i < 12; i++) mc->mpc_productid[i] = ' '; + +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_DEBUG, "MP_Tables: Init MP Configuration Table Header:\n" + "\tSignature\t\t: %4.4s\n" + "\tLength\t\t\t: 0x%x (Only Header, no other entries)\n" + "\tMP Specification\t: 0x%x\n" + "\tChecksum\t\t: 0x%x (Not calculated yet)\n" + "\tOEM ID\t\t\t: %8.8s\n" + "\tProduct ID\t\t: %12.12s\n" + "\tOEM Table PTR\t\t: 0x%x\n" + "\tOEM Table Size\t\t: 0x%x (Not filled in yet)\n" + "\tEntry Count\t\t: 0x%x (No entries created yet)\n" + "\tMMIO LAPIC Address\t: 0x%x\n" + "\tExtended Table Length\t: 0x%x (Not filled in yet)\n" + "\tExtended Table Checksum\t: 0x%x (Not calculated yet)\n", + mc->mpc_signature, mc->mpc_length, mc->mpc_spec, mc->mpc_checksum, + mc->mpc_oem, mc->mpc_productid, mc->mpc_oemptr, mc->mpc_oemsize, + mc->mpc_entry_count, mc->mpc_lapic, mc->mpe_length, mc->mpe_checksum); +#endif }
static unsigned char smp_compute_checksum(void *v, int len) @@ -94,6 +117,24 @@ static void *smp_write_floating_table_physaddr(u32 addr, u32 mpf_physptr, unsign mf->mpf_feature4 = 0; mf->mpf_feature5 = 0; mf->mpf_checksum = smp_compute_checksum(mf, mf->mpf_length*16); + +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_DEBUG, "MP_Tables: Add MP Floating Pointer Structure:\n" + "\tSignature\t\t: %4.4s\n" + "\tPhysical Pointer\t: 0x%x\n" + "\tLength\t\t\t: %d Paragraph(s) (16-bytes each)\n" + "\tMP Specification\t: 0x%x\n" + "\tChecksum\t\t: 0x%x\n" + "\tFeature1\t\t: 0x%x (Should be 0)\n" + "\tFeature2\t\t: '%s'\n" + "\tFeature3\t\t: 0x%x\n" + "\tFeature4\t\t: 0x%x\n" + "\tFeature5\t\t: 0x%x\n", + mf->mpf_signature, mpf_physptr, mf->mpf_length, mf->mpf_specification, + mf->mpf_checksum, mf->mpf_feature1, virtualwire?"PIC Mode":"Virtual Wire Mode", + mf->mpf_feature3, mf->mpf_feature4, mf->mpf_feature5); +#endif + return v; }
@@ -101,6 +142,8 @@ void *smp_write_floating_table(unsigned long addr, unsigned int virtualwire) { /* 16 byte align the table address */ addr = (addr + 0xf) & (~0xf); + + printk(BIOS_INFO, "MP_Tables: Start writing the MP_Tables at 0x%lx\n", addr); return smp_write_floating_table_physaddr(addr, addr + SMP_FLOATING_TABLE_LEN, virtualwire); }
@@ -138,6 +181,10 @@ void smp_write_processor(struct mp_config_table *mc, u8 apicid, u8 apicver, u8 cpuflag, u32 cpufeature, u32 featureflag) { +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_DEBUG, "\n\tAdd CPU/LAPIC Entry (Type 0)\n"); +#endif + struct mpc_config_processor *mpc; mpc = smp_next_mpc_entry(mc); memset(mpc, '\0', sizeof(*mpc)); @@ -147,6 +194,22 @@ void smp_write_processor(struct mp_config_table *mc, mpc->mpc_cpuflag = cpuflag; mpc->mpc_cpufeature = cpufeature; mpc->mpc_featureflag = featureflag; + +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_SPEW, + "\tID\t\t: 0x%x\n" + "\tVersion\t\t: 0x%x\n" + "\tFlags\t\t: 0x%x (%s%s)\n" + "\tCPU Signature 0x%x:\n" + "\t (Family %d, Model %d, Stepping %d)\n" + "\tFeature Flag\t: 0x%x (See CPUID)\n", + apicid, apicver, cpuflag, + (cpuflag & 0x1) ? "Enabled" : "Disabled", + (cpuflag & 0x2) ? ", Bootstrap" : "", + cpufeature, (cpufeature >> 8) & 0x0F, (cpufeature >> 4) & 0x0F, + cpufeature & 0x0F, featureflag); +#endif + smp_add_mpc_entry(mc, sizeof(*mpc)); }
@@ -207,12 +270,24 @@ void smp_write_processors(struct mp_config_table *mc) static void smp_write_bus(struct mp_config_table *mc, u8 id, const char *bustype) { +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_DEBUG, "\n\tAdd Bus Entry (Type 1)\n"); +#endif + struct mpc_config_bus *mpc; mpc = smp_next_mpc_entry(mc); memset(mpc, '\0', sizeof(*mpc)); mpc->mpc_type = MP_BUS; mpc->mpc_busid = id; memcpy(mpc->mpc_bustype, bustype, sizeof(mpc->mpc_bustype)); + +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_SPEW, + "\tBus ID\t\t: 0x%x\n" + "\tBus Type\t: '%s'\n", + id, bustype); +#endif + smp_add_mpc_entry(mc, sizeof(*mpc)); }
@@ -224,6 +299,9 @@ static void smp_write_bus(struct mp_config_table *mc, void smp_write_ioapic(struct mp_config_table *mc, u8 id, u8 ver, u32 apicaddr) { +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_DEBUG, "\n\tAdd IOAPIC Entry (Type 2)\n"); +#endif struct mpc_config_ioapic *mpc; mpc = smp_next_mpc_entry(mc); memset(mpc, '\0', sizeof(*mpc)); @@ -232,10 +310,85 @@ void smp_write_ioapic(struct mp_config_table *mc, mpc->mpc_apicver = ver; mpc->mpc_flags = MPC_APIC_USABLE; mpc->mpc_apicaddr = apicaddr; + +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_SPEW, + "\tID\t\t: 0x%x\n" + "\tVersion\t\t: 0x%x\n" + "\tFlags\t\t: 0x%x (%s)\n" + "\tAddress\t\t: 0x%x\n", + id, ver, mpc->mpc_flags, mpc->mpc_flags ? "Useable" : "Unusable", + apicaddr); +#endif + smp_add_mpc_entry(mc, sizeof(*mpc)); }
/* + * Type 3 and 4 MP entries have identical IRQ Types + * where an integer corresponds to a type which is + * easier to understand as a string + */ +const char * smp_irqtype_to_str(u8 irqtype) +{ + const char * str[] = { + "Vectored INT", + "NMI", + "SMI", + "ExtINT", + }; + + if (irqtype < 4) + return str[irqtype]; + else + return "Unknown IRQ Type"; +} + +/* + * Type 3 and 4 MP entries have an irqflag field + * that has (Polarity << 2) | (Trigger) data. This + * is much easier to read as a string for each MP + * entry that uses them + */ +char * smp_irqflag_to_str(u16 irqflag) +{ + int polarity = (irqflag & 0x3); /* Polarity is bottom 2 bits */ + int trigger = (irqflag >> 2) & 0x3; /* Trigger is next 2 bits */ + char str[1000]; + char * str_ptr; + int len = 0; + + str_ptr = str; + + /* IRQ Trigger polarity */ + const char * pol[] = { + "Bus Default", + "Active High", + "Reserved", + "Active Low", + }; + + /* IRQ Trigger mode */ + const char * trig[] = { + "Bus Default", + "Edge Triggered", + "Reserved", + "Level Triggered", + }; + + /* Create the Polarity|Trigger string */ + if ((strlen(pol[polarity]) + strlen("|") + strlen(trig[trigger]) + 1) < sizeof(str)) { + strcpy(str, pol[polarity]); + len = strlen(pol[polarity]); + strcpy(str + len, "|"); + len += strlen("|"); + strcpy(str + len, trig[trigger]); + } + + return str_ptr; +} + +/* * Type 3: I/O Interrupt Table Entries: * Entry Type, Int Type, Int Polarity, Int Level, * Source Bus ID, Source Bus IRQ, Dest APIC ID, Dest PIN# @@ -245,6 +398,10 @@ void smp_write_intsrc(struct mp_config_table *mc, u8 srcbus, u8 srcbusirq, u8 dstapic, u8 dstirq) { +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_DEBUG, "\n\tAdd IO Interrupt Entry (Type 3)\n"); +#endif + struct mpc_config_intsrc *mpc; mpc = smp_next_mpc_entry(mc); memset(mpc, '\0', sizeof(*mpc)); @@ -255,12 +412,21 @@ void smp_write_intsrc(struct mp_config_table *mc, mpc->mpc_srcbusirq = srcbusirq; mpc->mpc_dstapic = dstapic; mpc->mpc_dstirq = dstirq; - smp_add_mpc_entry(mc, sizeof(*mpc)); -#ifdef DEBUG_MPTABLE - printk(BIOS_DEBUG, "add intsrc srcbus 0x%x srcbusirq 0x%x, dstapic 0x%x, dstirq 0x%x\n", - srcbus, srcbusirq, dstapic, dstirq); - hexdump(__func__, mpc, sizeof(*mpc)); + +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_SPEW, + "\tIRQ Type\t: 0x%x (%s)\n" + "\tIRQ Flags\t: 0x%x (%s)\n" + "\tSrc Bus ID\t: 0x%x\n" + "\tSrc Bus IRQ\t: 0x%x\n" + "\tDest IOAPIC\t: 0x%x\n" + "\tDest IOAPIC IRQ\t: 0x%x\n", + irqtype, smp_irqtype_to_str(irqtype), + irqflag, smp_irqflag_to_str(irqflag), + srcbus, srcbusirq, dstapic, dstirq); #endif + + smp_add_mpc_entry(mc, sizeof(*mpc)); }
/* @@ -343,6 +509,10 @@ void smp_write_lintsrc(struct mp_config_table *mc, u8 srcbusid, u8 srcbusirq, u8 destapic, u8 destapiclint) { +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_DEBUG, "\n\tAdd Local Interrupt Entry (Type 4)\n"); +#endif + struct mpc_config_lintsrc *mpc; mpc = smp_next_mpc_entry(mc); memset(mpc, '\0', sizeof(*mpc)); @@ -353,6 +523,20 @@ void smp_write_lintsrc(struct mp_config_table *mc, mpc->mpc_srcbusirq = srcbusirq; mpc->mpc_destapic = destapic; mpc->mpc_destapiclint = destapiclint; + +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_SPEW, + "\tIRQ Type\t: 0x%x (%s)\n" + "\tIRQ Flags\t: 0x%x (%s)\n" + "\tSrc Bus ID\t: 0x%x\n" + "\tSrc Bus IRQ\t: 0x%x\n" + "\tDest LAPIC\t: 0x%x\n" + "\tDest LAPIC IRQ\t: 0x%x\n", + irqtype, smp_irqtype_to_str(irqtype), + irqflag, smp_irqflag_to_str(irqflag), + srcbusid, srcbusirq, destapic, destapiclint); +#endif + smp_add_mpc_entry(mc, sizeof(*mpc)); }
@@ -366,6 +550,10 @@ void smp_write_address_space(struct mp_config_table *mc, u32 address_base_low, u32 address_base_high, u32 address_length_low, u32 address_length_high) { +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_DEBUG, "\n\tAdd Address Space Mapping Entry (Type 128)\n"); +#endif + struct mp_exten_system_address_space *mpe; mpe = smp_next_mpe_entry(mc); memset(mpe, '\0', sizeof(*mpe)); @@ -377,6 +565,18 @@ void smp_write_address_space(struct mp_config_table *mc, mpe->mpe_address_base_high = address_base_high; mpe->mpe_address_length_low = address_length_low; mpe->mpe_address_length_high = address_length_high; + +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_SPEW, + "\tEntry Length\t: 0x%x\n" + "\tBus ID\t\t: 0x%x\n" + "\tAddress Type\t: 0x%x\n" + "\tAddress Base\t: 0x%x%x\n" + "\tAddress Length\t: 0x%x%x\n", + mpe->mpe_length, busid, address_type, address_base_high, address_base_low, + address_length_high, address_length_low); +#endif + smp_add_mpe_entry(mc, (mpe_t)mpe); }
@@ -388,6 +588,10 @@ void smp_write_address_space(struct mp_config_table *mc, void smp_write_bus_hierarchy(struct mp_config_table *mc, u8 busid, u8 bus_info, u8 parent_busid) { +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_DEBUG, "\n\tAdd Bus Hierarchy Entry (Type 129)\n"); +#endif + struct mp_exten_bus_hierarchy *mpe; mpe = smp_next_mpe_entry(mc); memset(mpe, '\0', sizeof(*mpe)); @@ -396,6 +600,16 @@ void smp_write_bus_hierarchy(struct mp_config_table *mc, mpe->mpe_busid = busid; mpe->mpe_bus_info = bus_info; mpe->mpe_parent_busid = parent_busid; + +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_SPEW, + "\tEntry Length\t: 0x%x\n" + "\tBus ID\t\t: 0x%x\n" + "\tBus Info\t: 0x%x\n" + "\tParent Bus ID\t: 0x%x\n", + mpe->mpe_length, busid, bus_info, parent_busid); +#endif + smp_add_mpe_entry(mc, (mpe_t)mpe); }
@@ -408,6 +622,10 @@ void smp_write_compatibility_address_space(struct mp_config_table *mc, u8 busid, u8 address_modifier, u32 range_list) { +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_DEBUG, "\n\tAdd Compatibility Address Space Entry (Type 130)\n"); +#endif + struct mp_exten_compatibility_address_space *mpe; mpe = smp_next_mpe_entry(mc); memset(mpe, '\0', sizeof(*mpe)); @@ -416,6 +634,16 @@ void smp_write_compatibility_address_space(struct mp_config_table *mc, mpe->mpe_busid = busid; mpe->mpe_address_modifier = address_modifier; mpe->mpe_range_list = range_list; + +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_SPEW, + "\tEntry Length\t: 0x%x\n" + "\tBus ID\t\t: 0x%x\n" + "\tAddress Modifier: 0x%x\n" + "\tRange List\t: 0x%x\n", + mpe->mpe_length, busid, address_modifier, range_list); +#endif + smp_add_mpe_entry(mc, (mpe_t)mpe); }
@@ -482,10 +710,41 @@ void mptable_write_buses(struct mp_config_table *mc, int *max_pci_bus, int *isa_
void *mptable_finalize(struct mp_config_table *mc) { - mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length); + void *last_mpc_entry = smp_next_mpc_entry(mc); + void *last_mpe_entry = smp_next_mpe_entry(mc); + + mc->mpe_checksum = smp_compute_checksum(last_mpc_entry, mc->mpe_length); mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length); - printk(BIOS_DEBUG, "Wrote the mp table end at: %p - %p\n", mc, smp_next_mpe_entry(mc)); - return smp_next_mpe_entry(mc); + printk(BIOS_INFO, "MP_Tables: Finished writing the MP_Table from 0x%p - 0x%p\n", mc, last_mpe_entry); + +#if IS_ENABLED(CONFIG_DEBUG_MP_TABLE) + printk(BIOS_DEBUG, "MP_Tables: Final MP Configuration Table Header:\n" + "\tSignature\t\t: %4.4s\n" + "\tLength\t\t\t: 0x%x\n" + "\tMP Specification\t: 0x%x\n" + "\tChecksum\t\t: 0x%x\n" + "\tOEM ID\t\t\t: %8.8s\n" + "\tProduct ID\t\t: %12.12s\n" + "\tOEM Table PTR\t\t: 0x%x\n" + "\tOEM Table Size\t\t: 0x%x\n" + "\tEntry Count\t\t: 0x%x\n" + "\tMMIO LAPIC Address\t: 0x%x\n" + "\tExtended Table Length\t: 0x%x\n" + "\tExtended Table Checksum\t: 0x%x\n", + mc->mpc_signature, mc->mpc_length, mc->mpc_spec, mc->mpc_checksum, + mc->mpc_oem, mc->mpc_productid, mc->mpc_oemptr, mc->mpc_oemsize, + mc->mpc_entry_count, mc->mpc_lapic, mc->mpe_length, mc->mpe_checksum); + + printk(BIOS_SPEW, "\nMP_Tables: Hexdump of the MP Configuration Table (0x%x bytes):\n", mc->mpc_length); + hexdump32(BIOS_SPEW, mc, mc->mpc_length / 4); + + if(mc->mpe_length){ + printk(BIOS_SPEW, "\nMP_Tables: Hexdump of the MP Extended Table (0x%x bytes):\n", mc->mpe_length); + hexdump32(BIOS_SPEW, last_mpc_entry, mc->mpe_length / 4); + } +#endif + + return last_mpe_entry; }
unsigned long __attribute__((weak)) write_smp_table(unsigned long addr) diff --git a/src/arch/x86/include/arch/smp/mpspec.h b/src/arch/x86/include/arch/smp/mpspec.h index 61709ff..cb7b727 100644 --- a/src/arch/x86/include/arch/smp/mpspec.h +++ b/src/arch/x86/include/arch/smp/mpspec.h @@ -261,6 +261,8 @@ void smp_write_processor(struct mp_config_table *mc, void smp_write_processors(struct mp_config_table *mc); void smp_write_ioapic(struct mp_config_table *mc, u8 id, u8 ver, u32 apicaddr); +const char * smp_irqtype_to_str(u8 irqtype); +char * smp_irqflag_to_str(u16 irqflag); void smp_write_intsrc(struct mp_config_table *mc, u8 irqtype, u16 irqflag, u8 srcbus, u8 srcbusirq, u8 dstapic, u8 dstirq);