[coreboot-gerrit] Patch set updated for coreboot: 30930fd MP Spec: Add debugging capabilities
Mike Loptien (mike.loptien@se-eng.com)
gerrit at coreboot.org
Mon Jun 16 19:27:19 CEST 2014
Mike Loptien (mike.loptien at se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5978
-gerrit
commit 30930fd7684c48e631b9791c5992835845f7d819
Author: Mike Loptien <mike.loptien at 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 at se-eng.com>
---
src/Kconfig | 14 ++
src/arch/x86/boot/mpspec.c | 272 ++++++++++++++++++++++++++++++++-
src/arch/x86/include/arch/smp/mpspec.h | 2 +
3 files changed, 281 insertions(+), 7 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..f3d434b 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));
@@ -148,6 +195,22 @@ void smp_write_processor(struct mp_config_table *mc,
mpc->mpc_cpufeature = cpufeature;
mpc->mpc_featureflag = featureflag;
smp_add_mpc_entry(mc, sizeof(*mpc));
+
+#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
+
}
/*
@@ -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));
@@ -256,10 +413,18 @@ void smp_write_intsrc(struct mp_config_table *mc,
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
}
@@ -343,6 +508,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 +522,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 +549,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 +564,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 +587,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 +599,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 +621,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 +633,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 +709,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);
More information about the coreboot-gerrit
mailing list