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 df3277053b3249124e245b4118f808d013066aaa 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.
Also add a function for PCI I/O interrupts since these are handled slightly differently than the other I/O interrupt entries. The src_bus_irq field is defined where Bits 1-0: PIRQ pin: INT_A# = 0, INT_B# = 1, INT_C# = 2, INT_D# = 3 Bits 2-6: Originating PCI Device Number Bit 7: Reserved
The elements in the MP Spec structures are also updated with appropriate types to more accurately reflect the real sizes of the bit fields in the MP Tables.
Change-Id: I13a446043c5094a680eb7461ec4b61427b7a7050 Signed-off-by: Mike Loptien mike.loptien@se-eng.com --- src/Kconfig | 14 ++ src/arch/x86/boot/mpspec.c | 387 ++++++++++++++++++++++++++++++--- src/arch/x86/include/arch/smp/mpspec.h | 182 ++++++++-------- 3 files changed, 458 insertions(+), 125 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 cd2b142..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) @@ -73,7 +96,7 @@ static unsigned char smp_compute_checksum(void *v, int len) return checksum; }
-static void *smp_write_floating_table_physaddr(unsigned long addr, unsigned long mpf_physptr, unsigned int virtualwire) +static void *smp_write_floating_table_physaddr(u32 addr, u32 mpf_physptr, unsigned int virtualwire) { struct intel_mp_floating *mf; void *v; @@ -94,6 +117,24 @@ static void *smp_write_floating_table_physaddr(unsigned long addr, unsigned long 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); }
@@ -108,9 +151,10 @@ void *smp_next_mpc_entry(struct mp_config_table *mc) { void *v; v = (void *)(((char *)mc) + mc->mpc_length); + return v; } -static void smp_add_mpc_entry(struct mp_config_table *mc, unsigned length) +static void smp_add_mpc_entry(struct mp_config_table *mc, u16 length) { mc->mpc_length += length; mc->mpc_entry_count++; @@ -120,6 +164,7 @@ void *smp_next_mpe_entry(struct mp_config_table *mc) { void *v; v = (void *)(((char *)mc) + mc->mpc_length + mc->mpe_length); + return v; } static void smp_add_mpe_entry(struct mp_config_table *mc, mpe_t mpe) @@ -127,11 +172,19 @@ static void smp_add_mpe_entry(struct mp_config_table *mc, mpe_t mpe) mc->mpe_length += mpe->mpe_length; }
+/* + * Type 0: Processor Entries: + * Entry Type, LAPIC ID, LAPIC Version, CPU Flags EN/BP, + * CPU Signature (Stepping, Model, Family), Feature Flags + */ void smp_write_processor(struct mp_config_table *mc, - unsigned char apicid, unsigned char apicver, - unsigned char cpuflag, unsigned int cpufeature, - unsigned int featureflag) + 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)); @@ -141,10 +194,27 @@ 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)); }
-/* If we assume a symmetric processor configuration we can +/* + * If we assume a symmetric processor configuration we can * get all of the information we need to write the processor * entry from the bootstrap processor. * Plus I don't think linux really even cares. @@ -183,8 +253,9 @@ void smp_write_processors(struct mp_config_table *mc) cpu_flag = MPC_CPU_ENABLED | MPC_CPU_BOOTPROCESSOR;
if(cpu->path.apic.apic_id == order_id) { - smp_write_processor(mc, cpu->path.apic.apic_id, apic_version, - cpu_flag, cpu_features, cpu_feature_flags + smp_write_processor(mc, + cpu->path.apic.apic_id, apic_version, + cpu_flag, cpu_features, cpu_feature_flags ); break; } @@ -192,22 +263,45 @@ void smp_write_processors(struct mp_config_table *mc) } }
+/* + * Type 1: Bus Entries: + * Entry Type, Bus ID, Bus Type + */ static void smp_write_bus(struct mp_config_table *mc, - unsigned char id, const char *bustype) + 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)); }
+/* + * Type 2: I/O APIC Entries: + * Entry Type, APIC ID, Version, + * APIC Flags:EN, Address + */ void smp_write_ioapic(struct mp_config_table *mc, - unsigned char id, unsigned char ver, - unsigned long apicaddr) + 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)); @@ -216,14 +310,98 @@ 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# + */ void smp_write_intsrc(struct mp_config_table *mc, - unsigned char irqtype, unsigned short irqflag, - unsigned char srcbus, unsigned char srcbusirq, - unsigned char dstapic, unsigned char dstirq) + u8 irqtype, u16 irqflag, + 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)); @@ -234,17 +412,44 @@ 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)); +} + +/* + * Type 3: I/O Interrupt Table Entries for PCI Devices: + * This has the same fields as 'Type 3: I/O Interrupt Table Entries' + * but the Source Bus IRQ field has a slightly different + * definition: + * Bits 1-0: PIRQ pin: INT_A# = 0, INT_B# = 1, INT_C# = 2, INT_D# = 3 + * Bits 2-6: Originating PCI Device Number (Not its parent bridge device number) + * Bit 7: Reserved + */ +void smp_write_pci_intsrc(struct mp_config_table *mc, + u8 irqtype, u8 srcbus, u8 dev, u8 pirq, + u8 dstapic, u8 dstirq) +{ + u8 srcbusirq = (dev << 2) | pirq; + printk(BIOS_SPEW, "\tPCI srcbusirq = 0x%x from dev = 0x%x and pirq = %x\n", srcbusirq, dev, pirq); + smp_write_intsrc(mc, irqtype, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, srcbus, + srcbusirq, dstapic, dstirq); }
void smp_write_intsrc_pci_bridge(struct mp_config_table *mc, - unsigned char irqtype, unsigned short irqflag, - struct device *dev, + u8 irqtype, u16 irqflag, struct device *dev, unsigned char dstapic, unsigned char *dstirq) { struct device *child; @@ -293,11 +498,21 @@ next: } }
+/* + * Type 4: Local Interrupt Assignment Entries: + * Entry Type, Int Type, Int Polarity, Int Level, + * Source Bus ID, Source Bus IRQ, Dest LAPIC ID, + * Dest LAPIC LINTIN# + */ void smp_write_lintsrc(struct mp_config_table *mc, - unsigned char irqtype, unsigned short irqflag, - unsigned char srcbusid, unsigned char srcbusirq, - unsigned char destapic, unsigned char destapiclint) + u8 irqtype, u16 irqflag, + 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)); @@ -308,14 +523,37 @@ 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)); }
+/* + * Type 128: System Address Space Mapping Entries + * Entry Type, Entry Length, Bus ID, Address Type, + * Address Base Lo/Hi, Address Length Lo/Hi + */ void smp_write_address_space(struct mp_config_table *mc, - unsigned char busid, unsigned char address_type, - unsigned int address_base_low, unsigned int address_base_high, - unsigned int address_length_low, unsigned int address_length_high) + u8 busid, u8 address_type, + 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)); @@ -327,14 +565,33 @@ 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); }
- +/* + * Type 129: Bus Hierarchy Descriptor Entry + * Entry Type, Entry Length, Bus ID, Bus Info, + * Parent Bus ID + */ void smp_write_bus_hierarchy(struct mp_config_table *mc, - unsigned char busid, unsigned char bus_info, - unsigned char parent_busid) + 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)); @@ -343,13 +600,32 @@ 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); }
+/* + * Type 130: Compatibility Bus Address Space Modifier Entry + * Entry Type, Entry Length, Bus ID, Address Modifier + * Predefined Range List + */ void smp_write_compatibility_address_space(struct mp_config_table *mc, - unsigned char busid, unsigned char address_modifier, - unsigned int range_list) + 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)); @@ -358,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); }
@@ -424,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 725718a..4979ff3 100644 --- a/src/arch/x86/include/arch/smp/mpspec.h +++ b/src/arch/x86/include/arch/smp/mpspec.h @@ -45,36 +45,36 @@
struct intel_mp_floating { - char mpf_signature[4]; /* "_MP_" */ - unsigned long mpf_physptr; /* Configuration table address */ - unsigned char mpf_length; /* Our length (paragraphs) */ - unsigned char mpf_specification;/* Specification version */ - unsigned char mpf_checksum; /* Checksum (makes sum 0) */ - unsigned char mpf_feature1; /* Standard or configuration ? */ - unsigned char mpf_feature2; /* Bit7 set for IMCR|PIC */ + char mpf_signature[4]; /* "_MP_" */ + u32 mpf_physptr; /* Configuration table address */ + u8 mpf_length; /* Our length (paragraphs) */ + u8 mpf_specification;/* Specification version */ + u8 mpf_checksum; /* Checksum (makes sum 0) */ + u8 mpf_feature1; /* Predefined or Unique configuration? */ + u8 mpf_feature2; /* Bit7 set for IMCR/PIC */ #define MP_FEATURE_VIRTUALWIRE (0 << 7) #define MP_FEATURE_PIC (1 << 7) - unsigned char mpf_feature3; /* Unused (0) */ - unsigned char mpf_feature4; /* Unused (0) */ - unsigned char mpf_feature5; /* Unused (0) */ + u8 mpf_feature3; /* Unused (0) */ + u8 mpf_feature4; /* Unused (0) */ + u8 mpf_feature5; /* Unused (0) */ } __attribute__((packed));
struct mp_config_table { char mpc_signature[4]; #define MPC_SIGNATURE "PCMP" - unsigned short mpc_length; /* Size of table */ - char mpc_spec; /* 0x01 */ - char mpc_checksum; + u16 mpc_length; /* Size of table */ + u8 mpc_spec; /* 0x01 */ + u8 mpc_checksum; char mpc_oem[8]; char mpc_productid[12]; - unsigned long mpc_oemptr; /* 0 if not present */ - unsigned short mpc_oemsize; /* 0 if not present */ - unsigned short mpc_entry_count; - unsigned long mpc_lapic; /* APIC address */ - unsigned short mpe_length; /* Extended Table size */ - unsigned char mpe_checksum; /* Extended Table checksum */ - unsigned char reserved; + u32 mpc_oemptr; /* 0 if not present */ + u16 mpc_oemsize; /* 0 if not present */ + u16 mpc_entry_count; + u32 mpc_lapic; /* APIC address */ + u16 mpe_length; /* Extended Table size */ + u8 mpe_checksum; /* Extended Table checksum */ + u8 reserved; } __attribute__((packed));
/* Followed by entries */ @@ -87,25 +87,25 @@ struct mp_config_table
struct mpc_config_processor { - unsigned char mpc_type; - unsigned char mpc_apicid; /* Local APIC number */ - unsigned char mpc_apicver; /* Its versions */ - unsigned char mpc_cpuflag; + u8 mpc_type; + u8 mpc_apicid; /* Local APIC number */ + u8 mpc_apicver; /* Its versions */ + u8 mpc_cpuflag; #define MPC_CPU_ENABLED 1 /* Processor is available */ #define MPC_CPU_BOOTPROCESSOR 2 /* Processor is the BP */ - unsigned long mpc_cpufeature; + u32 mpc_cpufeature; #define MPC_CPU_STEPPING_MASK 0x0F #define MPC_CPU_MODEL_MASK 0xF0 #define MPC_CPU_FAMILY_MASK 0xF00 - unsigned long mpc_featureflag; /* CPUID feature value */ - unsigned long mpc_reserved[2]; + u32 mpc_featureflag; /* CPUID feature value */ + u32 mpc_reserved[2]; } __attribute__((packed));
struct mpc_config_bus { - unsigned char mpc_type; - unsigned char mpc_busid; - unsigned char mpc_bustype[6]; + u8 mpc_type; + u8 mpc_busid; + u8 mpc_bustype[6]; } __attribute__((packed));
#define BUSTYPE_EISA "EISA" @@ -118,23 +118,23 @@ struct mpc_config_bus
struct mpc_config_ioapic { - unsigned char mpc_type; - unsigned char mpc_apicid; - unsigned char mpc_apicver; - unsigned char mpc_flags; + u8 mpc_type; + u8 mpc_apicid; + u8 mpc_apicver; + u8 mpc_flags; #define MPC_APIC_USABLE 0x01 - unsigned long mpc_apicaddr; + u32 mpc_apicaddr; } __attribute__((packed));
struct mpc_config_intsrc { - unsigned char mpc_type; - unsigned char mpc_irqtype; - unsigned short mpc_irqflag; - unsigned char mpc_srcbus; - unsigned char mpc_srcbusirq; - unsigned char mpc_dstapic; - unsigned char mpc_dstirq; + u8 mpc_type; + u8 mpc_irqtype; + u16 mpc_irqflag; + u8 mpc_srcbus; + u8 mpc_srcbusirq; + u8 mpc_dstapic; + u8 mpc_dstirq; } __attribute__((packed));
enum mp_irq_source_types { @@ -156,14 +156,14 @@ enum mp_irq_source_types {
struct mpc_config_lintsrc { - unsigned char mpc_type; - unsigned char mpc_irqtype; - unsigned short mpc_irqflag; - unsigned char mpc_srcbusid; - unsigned char mpc_srcbusirq; - unsigned char mpc_destapic; + u8 mpc_type; + u8 mpc_irqtype; + u16 mpc_irqflag; + u8 mpc_srcbusid; + u8 mpc_srcbusirq; + u8 mpc_destapic; #define MP_APIC_ALL 0xFF - unsigned char mpc_destapiclint; + u8 mpc_destapiclint; } __attribute__((packed));
/* @@ -194,44 +194,44 @@ enum mp_bustype { #define MPE_COMPATIBILITY_ADDRESS_SPACE 0x82
struct mp_exten_config { - unsigned char mpe_type; - unsigned char mpe_length; + u8 mpe_type; + u8 mpe_length; } __attribute__((packed));
typedef struct mp_exten_config *mpe_t;
struct mp_exten_system_address_space { - unsigned char mpe_type; - unsigned char mpe_length; - unsigned char mpe_busid; - unsigned char mpe_address_type; + u8 mpe_type; + u8 mpe_length; + u8 mpe_busid; + u8 mpe_address_type; #define ADDRESS_TYPE_IO 0 #define ADDRESS_TYPE_MEM 1 #define ADDRESS_TYPE_PREFETCH 2 - unsigned int mpe_address_base_low; - unsigned int mpe_address_base_high; - unsigned int mpe_address_length_low; - unsigned int mpe_address_length_high; + u32 mpe_address_base_low; + u32 mpe_address_base_high; + u32 mpe_address_length_low; + u32 mpe_address_length_high; } __attribute__((packed));
struct mp_exten_bus_hierarchy { - unsigned char mpe_type; - unsigned char mpe_length; - unsigned char mpe_busid; - unsigned char mpe_bus_info; + u8 mpe_type; + u8 mpe_length; + u8 mpe_busid; + u8 mpe_bus_info; #define BUS_SUBTRACTIVE_DECODE 1 - unsigned char mpe_parent_busid; - unsigned char reserved[3]; + u8 mpe_parent_busid; + u8 reserved[3]; } __attribute__((packed));
struct mp_exten_compatibility_address_space { - unsigned char mpe_type; - unsigned char mpe_length; - unsigned char mpe_busid; - unsigned char mpe_address_modifier; + u8 mpe_type; + u8 mpe_length; + u8 mpe_busid; + u8 mpe_address_modifier; #define ADDRESS_RANGE_SUBTRACT 1 #define ADDRESS_RANGE_ADD 0 - unsigned int mpe_range_list; + u32 mpe_range_list; #define RANGE_LIST_IO_ISA 0 /* X100 - X3FF * X500 - X7FF @@ -251,40 +251,42 @@ struct mp_exten_compatibility_address_space { } __attribute__((packed));
void mptable_init(struct mp_config_table *mc, u32 lapic_addr); - void *smp_next_mpc_entry(struct mp_config_table *mc); void *smp_next_mpe_entry(struct mp_config_table *mc);
void smp_write_processor(struct mp_config_table *mc, - unsigned char apicid, unsigned char apicver, - unsigned char cpuflag, unsigned int cpufeature, - unsigned int featureflag); + u8 apicid, u8 apicver, + u8 cpuflag, u32 cpufeature, + u32 featureflag); void smp_write_processors(struct mp_config_table *mc); void smp_write_ioapic(struct mp_config_table *mc, - unsigned char id, unsigned char ver, - unsigned long apicaddr); + 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, - unsigned char irqtype, unsigned short irqflag, - unsigned char srcbus, unsigned char srcbusirq, - unsigned char dstapic, unsigned char dstirq); + u8 irqtype, u16 irqflag, u8 srcbus, u8 srcbusirq, + u8 dstapic, u8 dstirq); +void smp_write_pci_intsrc(struct mp_config_table *mc, + u8 irqtype, u8 srcbus, u8 dev, u8 pirq, + u8 dstapic, u8 dstirq); void smp_write_intsrc_pci_bridge(struct mp_config_table *mc, - unsigned char irqtype, unsigned short irqflag, + u8 irqtype, u16 irqflag, struct device *dev, unsigned char dstapic, unsigned char *dstirq); void smp_write_lintsrc(struct mp_config_table *mc, - unsigned char irqtype, unsigned short irqflag, - unsigned char srcbusid, unsigned char srcbusirq, - unsigned char destapic, unsigned char destapiclint); + u8 irqtype, u16 irqflag, + u8 srcbusid, u8 srcbusirq, + u8 destapic, u8 destapiclint); void smp_write_address_space(struct mp_config_table *mc, - unsigned char busid, unsigned char address_type, - unsigned int address_base_low, unsigned int address_base_high, - unsigned int address_length_low, unsigned int address_length_high); + u8 busid, u8 address_type, + u32 address_base_low, u32 address_base_high, + u32 address_length_low, u32 address_length_high); void smp_write_bus_hierarchy(struct mp_config_table *mc, - unsigned char busid, unsigned char bus_info, - unsigned char parent_busid); + u8 busid, u8 bus_info, + u8 parent_busid); void smp_write_compatibility_address_space(struct mp_config_table *mc, - unsigned char busid, unsigned char address_modifier, - unsigned int range_list); + u8 busid, u8 address_modifier, + u32 range_list); void *smp_write_floating_table(unsigned long addr, unsigned int virtualwire); unsigned long write_smp_table(unsigned long addr);