intelmp.cc revision 11793:ef606668d247
17008Snate@binkert.org/* 27008Snate@binkert.org * Copyright (c) 2008 The Hewlett-Packard Development Company 37008Snate@binkert.org * All rights reserved. 47008Snate@binkert.org * 57008Snate@binkert.org * The license below extends only to copyright in the software and shall 67008Snate@binkert.org * not be construed as granting a license to any other intellectual 77008Snate@binkert.org * property including but not limited to intellectual property relating 87008Snate@binkert.org * to a hardware implementation of the functionality of the software 97008Snate@binkert.org * licensed hereunder. You may use the software subject to the license 107008Snate@binkert.org * terms below provided that you ensure that this notice is replicated 117008Snate@binkert.org * unmodified and in its entirety in all distributions of the software, 127008Snate@binkert.org * modified or unmodified, in source code or in binary form. 137008Snate@binkert.org * 147008Snate@binkert.org * Redistribution and use in source and binary forms, with or without 157008Snate@binkert.org * modification, are permitted provided that the following conditions are 167008Snate@binkert.org * met: redistributions of source code must retain the above copyright 177008Snate@binkert.org * notice, this list of conditions and the following disclaimer; 187008Snate@binkert.org * redistributions in binary form must reproduce the above copyright 197008Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 207008Snate@binkert.org * documentation and/or other materials provided with the distribution; 217008Snate@binkert.org * neither the name of the copyright holders nor the names of its 227008Snate@binkert.org * contributors may be used to endorse or promote products derived from 237008Snate@binkert.org * this software without specific prior written permission. 247008Snate@binkert.org * 257008Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 267008Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 277008Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 286285Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 298232Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 309104Shestness@cs.utexas.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 317039Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 327039Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 336285Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 347039Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 356285Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 366285Snate@binkert.org * 376876Ssteve.reinhardt@amd.com * Authors: Gabe Black 387039Snate@binkert.org */ 396285Snate@binkert.org 406285Snate@binkert.org#include "arch/x86/bios/intelmp.hh" 416285Snate@binkert.org 427039Snate@binkert.org#include "arch/x86/isa_traits.hh" 437039Snate@binkert.org#include "base/misc.hh" 446285Snate@binkert.org#include "base/types.hh" 457039Snate@binkert.org#include "mem/port_proxy.hh" 467039Snate@binkert.org#include "sim/byteswap.hh" 477039Snate@binkert.org 486285Snate@binkert.org// Config entry types 496285Snate@binkert.org#include "params/X86IntelMPBaseConfigEntry.hh" 507039Snate@binkert.org#include "params/X86IntelMPExtConfigEntry.hh" 518615Snilay@cs.wisc.edu 526285Snate@binkert.org// General table structures 537544SBrad.Beckmann@amd.com#include "params/X86IntelMPConfigTable.hh" 547544SBrad.Beckmann@amd.com#include "params/X86IntelMPFloatingPointer.hh" 557544SBrad.Beckmann@amd.com 567544SBrad.Beckmann@amd.com// Base entry types 578615Snilay@cs.wisc.edu#include "params/X86IntelMPBus.hh" 588615Snilay@cs.wisc.edu#include "params/X86IntelMPIOAPIC.hh" 598615Snilay@cs.wisc.edu#include "params/X86IntelMPIOIntAssignment.hh" 608615Snilay@cs.wisc.edu#include "params/X86IntelMPLocalIntAssignment.hh" 616285Snate@binkert.org#include "params/X86IntelMPProcessor.hh" 627039Snate@binkert.org 637039Snate@binkert.org// Extended entry types 646285Snate@binkert.org#include "params/X86IntelMPAddrSpaceMapping.hh" 657039Snate@binkert.org#include "params/X86IntelMPBusHierarchy.hh" 667039Snate@binkert.org#include "params/X86IntelMPCompatAddrSpaceMod.hh" 677039Snate@binkert.org 687039Snate@binkert.orgusing namespace std; 697039Snate@binkert.org 707039Snate@binkert.orgconst char X86ISA::IntelMP::FloatingPointer::signature[] = "_MP_"; 718615Snilay@cs.wisc.edu 726285Snate@binkert.orgtemplate<class T> 737453Snate@binkert.orguint8_t 747453Snate@binkert.orgwriteOutField(PortProxy& proxy, Addr addr, T val) 757453Snate@binkert.org{ 767453Snate@binkert.org uint64_t guestVal = X86ISA::htog(val); 777039Snate@binkert.org proxy.writeBlob(addr, (uint8_t *)(&guestVal), sizeof(T)); 786888SBrad.Beckmann@amd.com 797453Snate@binkert.org uint8_t checkSum = 0; 807039Snate@binkert.org while (guestVal) { 816888SBrad.Beckmann@amd.com checkSum += guestVal; 827915SBrad.Beckmann@amd.com guestVal >>= 8; 837915SBrad.Beckmann@amd.com } 847915SBrad.Beckmann@amd.com return checkSum; 857915SBrad.Beckmann@amd.com} 867039Snate@binkert.org 876888SBrad.Beckmann@amd.comuint8_t 887039Snate@binkert.orgwriteOutString(PortProxy& proxy, Addr addr, string str, int length) 897039Snate@binkert.org{ 907453Snate@binkert.org char cleanedString[length + 1]; 916285Snate@binkert.org cleanedString[length] = 0; 927039Snate@binkert.org 936285Snate@binkert.org if (str.length() > length) { 946285Snate@binkert.org memcpy(cleanedString, str.c_str(), length); 957039Snate@binkert.org warn("Intel MP configuration table string \"%s\" " 967039Snate@binkert.org "will be truncated to \"%s\".\n", str, (char *)&cleanedString); 976285Snate@binkert.org } else { 987039Snate@binkert.org memcpy(cleanedString, str.c_str(), str.length()); 997039Snate@binkert.org memset(cleanedString + str.length(), 0, length - str.length()); 1007039Snate@binkert.org } 1018162SBrad.Beckmann@amd.com proxy.writeBlob(addr, (uint8_t *)(&cleanedString), length); 1028162SBrad.Beckmann@amd.com 1038162SBrad.Beckmann@amd.com uint8_t checkSum = 0; 1048162SBrad.Beckmann@amd.com for (int i = 0; i < length; i++) 1058162SBrad.Beckmann@amd.com checkSum += cleanedString[i]; 1068162SBrad.Beckmann@amd.com 1077039Snate@binkert.org return checkSum; 1087039Snate@binkert.org} 1097039Snate@binkert.org 1106285Snate@binkert.orgAddr 1117453Snate@binkert.orgX86ISA::IntelMP::FloatingPointer::writeOut(PortProxy& proxy, Addr addr) 1127453Snate@binkert.org{ 1137039Snate@binkert.org // Make sure that either a config table is present or a default 1146888SBrad.Beckmann@amd.com // configuration was found but not both. 1157453Snate@binkert.org if (!tableAddr && !defaultConfig) 1167453Snate@binkert.org fatal("Either an MP configuration table or a default configuration " 1176888SBrad.Beckmann@amd.com "must be used."); 1187453Snate@binkert.org if (tableAddr && defaultConfig) 1197039Snate@binkert.org fatal("Both an MP configuration table and a default configuration " 1206888SBrad.Beckmann@amd.com "were set."); 1217453Snate@binkert.org 1227039Snate@binkert.org uint8_t checkSum = 0; 1237039Snate@binkert.org 1247039Snate@binkert.org proxy.writeBlob(addr, (uint8_t *)signature, 4); 1257039Snate@binkert.org for (int i = 0; i < 4; i++) 1266888SBrad.Beckmann@amd.com checkSum += signature[i]; 1277039Snate@binkert.org 1287453Snate@binkert.org checkSum += writeOutField(proxy, addr + 4, tableAddr); 1297039Snate@binkert.org 1307453Snate@binkert.org // The length of the structure in paragraphs, aka 16 byte chunks. 1317453Snate@binkert.org uint8_t length = 1; 1327039Snate@binkert.org proxy.writeBlob(addr + 8, &length, 1); 1337453Snate@binkert.org checkSum += length; 1347039Snate@binkert.org 1356888SBrad.Beckmann@amd.com proxy.writeBlob(addr + 9, &specRev, 1); 1367039Snate@binkert.org checkSum += specRev; 1377039Snate@binkert.org 1387453Snate@binkert.org proxy.writeBlob(addr + 11, &defaultConfig, 1); 1398160SBrad.Beckmann@amd.com checkSum += defaultConfig; 1408160SBrad.Beckmann@amd.com 1418160SBrad.Beckmann@amd.com uint32_t features2_5 = imcrPresent ? (1 << 7) : 0; 1428160SBrad.Beckmann@amd.com checkSum += writeOutField(proxy, addr + 12, features2_5); 1436285Snate@binkert.org 1446285Snate@binkert.org checkSum = -checkSum; 1457039Snate@binkert.org proxy.writeBlob(addr + 10, &checkSum, 1); 1467039Snate@binkert.org 1476285Snate@binkert.org return 16; 1487039Snate@binkert.org} 1497039Snate@binkert.org 1507039Snate@binkert.orgX86ISA::IntelMP::FloatingPointer::FloatingPointer(Params * p) : 1517039Snate@binkert.org SimObject(p), tableAddr(0), specRev(p->spec_rev), 1527039Snate@binkert.org defaultConfig(p->default_config), imcrPresent(p->imcr_present) 1537039Snate@binkert.org{} 1547915SBrad.Beckmann@amd.com 1557915SBrad.Beckmann@amd.comX86ISA::IntelMP::FloatingPointer * 1567915SBrad.Beckmann@amd.comX86IntelMPFloatingPointerParams::create() 1577915SBrad.Beckmann@amd.com{ 1587039Snate@binkert.org return new X86ISA::IntelMP::FloatingPointer(this); 1596285Snate@binkert.org} 1606285Snate@binkert.org 1617039Snate@binkert.orgAddr 1627039Snate@binkert.orgX86ISA::IntelMP::BaseConfigEntry::writeOut(PortProxy& proxy, 1636285Snate@binkert.org Addr addr, uint8_t &checkSum) 1647039Snate@binkert.org{ 1656285Snate@binkert.org proxy.writeBlob(addr, &type, 1); 1666285Snate@binkert.org checkSum += type; 1677039Snate@binkert.org return 1; 1687055Snate@binkert.org} 1696285Snate@binkert.org 1706285Snate@binkert.orgX86ISA::IntelMP::BaseConfigEntry::BaseConfigEntry(Params * p, uint8_t _type) : 1716876Ssteve.reinhardt@amd.com SimObject(p), type(_type) 1729104Shestness@cs.utexas.edu{} 1739104Shestness@cs.utexas.edu 1749104Shestness@cs.utexas.eduAddr 1759104Shestness@cs.utexas.eduX86ISA::IntelMP::ExtConfigEntry::writeOut(PortProxy& proxy, 1769104Shestness@cs.utexas.edu Addr addr, uint8_t &checkSum) 1779104Shestness@cs.utexas.edu{ 1786876Ssteve.reinhardt@amd.com proxy.writeBlob(addr, &type, 1); 1796876Ssteve.reinhardt@amd.com checkSum += type; 1806876Ssteve.reinhardt@amd.com proxy.writeBlob(addr + 1, &length, 1); 1816876Ssteve.reinhardt@amd.com checkSum += length; 1826876Ssteve.reinhardt@amd.com return 1; 183} 184 185X86ISA::IntelMP::ExtConfigEntry::ExtConfigEntry(Params * p, 186 uint8_t _type, uint8_t _length) : 187 SimObject(p), type(_type), length(_length) 188{} 189 190const char X86ISA::IntelMP::ConfigTable::signature[] = "PCMP"; 191 192Addr 193X86ISA::IntelMP::ConfigTable::writeOut(PortProxy& proxy, Addr addr) 194{ 195 uint8_t checkSum = 0; 196 197 proxy.writeBlob(addr, (uint8_t *)signature, 4); 198 for (int i = 0; i < 4; i++) 199 checkSum += signature[i]; 200 201 // Base table length goes here but will be calculated later. 202 203 proxy.writeBlob(addr + 6, (uint8_t *)(&specRev), 1); 204 checkSum += specRev; 205 206 // The checksum goes here but is still being calculated. 207 208 checkSum += writeOutString(proxy, addr + 8, oemID, 8); 209 checkSum += writeOutString(proxy, addr + 16, productID, 12); 210 211 checkSum += writeOutField(proxy, addr + 28, oemTableAddr); 212 checkSum += writeOutField(proxy, addr + 32, oemTableSize); 213 checkSum += writeOutField(proxy, addr + 34, (uint16_t)baseEntries.size()); 214 checkSum += writeOutField(proxy, addr + 36, localApic); 215 216 uint8_t reserved = 0; 217 proxy.writeBlob(addr + 43, &reserved, 1); 218 checkSum += reserved; 219 220 vector<BaseConfigEntry *>::iterator baseEnt; 221 uint16_t offset = 44; 222 for (baseEnt = baseEntries.begin(); 223 baseEnt != baseEntries.end(); baseEnt++) { 224 offset += (*baseEnt)->writeOut(proxy, addr + offset, checkSum); 225 } 226 227 // We've found the end of the base table this point. 228 checkSum += writeOutField(proxy, addr + 4, offset); 229 230 vector<ExtConfigEntry *>::iterator extEnt; 231 uint16_t extOffset = 0; 232 uint8_t extCheckSum = 0; 233 for (extEnt = extEntries.begin(); 234 extEnt != extEntries.end(); extEnt++) { 235 extOffset += (*extEnt)->writeOut(proxy, 236 addr + offset + extOffset, extCheckSum); 237 } 238 239 checkSum += writeOutField(proxy, addr + 40, extOffset); 240 extCheckSum = -extCheckSum; 241 checkSum += writeOutField(proxy, addr + 42, extCheckSum); 242 243 // And now, we finally have the whole check sum completed. 244 checkSum = -checkSum; 245 writeOutField(proxy, addr + 7, checkSum); 246 247 return offset + extOffset; 248}; 249 250X86ISA::IntelMP::ConfigTable::ConfigTable(Params * p) : SimObject(p), 251 specRev(p->spec_rev), oemID(p->oem_id), productID(p->product_id), 252 oemTableAddr(p->oem_table_addr), oemTableSize(p->oem_table_size), 253 localApic(p->local_apic), 254 baseEntries(p->base_entries), extEntries(p->ext_entries) 255{} 256 257X86ISA::IntelMP::ConfigTable * 258X86IntelMPConfigTableParams::create() 259{ 260 return new X86ISA::IntelMP::ConfigTable(this); 261} 262 263Addr 264X86ISA::IntelMP::Processor::writeOut( 265 PortProxy& proxy, Addr addr, uint8_t &checkSum) 266{ 267 BaseConfigEntry::writeOut(proxy, addr, checkSum); 268 checkSum += writeOutField(proxy, addr + 1, localApicID); 269 checkSum += writeOutField(proxy, addr + 2, localApicVersion); 270 checkSum += writeOutField(proxy, addr + 3, cpuFlags); 271 checkSum += writeOutField(proxy, addr + 4, cpuSignature); 272 checkSum += writeOutField(proxy, addr + 8, featureFlags); 273 274 uint32_t reserved = 0; 275 proxy.writeBlob(addr + 12, (uint8_t *)(&reserved), 4); 276 proxy.writeBlob(addr + 16, (uint8_t *)(&reserved), 4); 277 return 20; 278} 279 280X86ISA::IntelMP::Processor::Processor(Params * p) : BaseConfigEntry(p, 0), 281 localApicID(p->local_apic_id), localApicVersion(p->local_apic_version), 282 cpuFlags(0), cpuSignature(0), featureFlags(p->feature_flags) 283{ 284 if (p->enable) 285 cpuFlags |= (1 << 0); 286 if (p->bootstrap) 287 cpuFlags |= (1 << 1); 288 289 replaceBits(cpuSignature, 0, 3, p->stepping); 290 replaceBits(cpuSignature, 4, 7, p->model); 291 replaceBits(cpuSignature, 8, 11, p->family); 292} 293 294X86ISA::IntelMP::Processor * 295X86IntelMPProcessorParams::create() 296{ 297 return new X86ISA::IntelMP::Processor(this); 298} 299 300Addr 301X86ISA::IntelMP::Bus::writeOut( 302 PortProxy& proxy, Addr addr, uint8_t &checkSum) 303{ 304 BaseConfigEntry::writeOut(proxy, addr, checkSum); 305 checkSum += writeOutField(proxy, addr + 1, busID); 306 checkSum += writeOutString(proxy, addr + 2, busType, 6); 307 return 8; 308} 309 310X86ISA::IntelMP::Bus::Bus(Params * p) : BaseConfigEntry(p, 1), 311 busID(p->bus_id), busType(p->bus_type) 312{} 313 314X86ISA::IntelMP::Bus * 315X86IntelMPBusParams::create() 316{ 317 return new X86ISA::IntelMP::Bus(this); 318} 319 320Addr 321X86ISA::IntelMP::IOAPIC::writeOut( 322 PortProxy& proxy, Addr addr, uint8_t &checkSum) 323{ 324 BaseConfigEntry::writeOut(proxy, addr, checkSum); 325 checkSum += writeOutField(proxy, addr + 1, id); 326 checkSum += writeOutField(proxy, addr + 2, version); 327 checkSum += writeOutField(proxy, addr + 3, flags); 328 checkSum += writeOutField(proxy, addr + 4, address); 329 return 8; 330} 331 332X86ISA::IntelMP::IOAPIC::IOAPIC(Params * p) : BaseConfigEntry(p, 2), 333 id(p->id), version(p->version), flags(0), address(p->address) 334{ 335 if (p->enable) 336 flags |= 1; 337} 338 339X86ISA::IntelMP::IOAPIC * 340X86IntelMPIOAPICParams::create() 341{ 342 return new X86ISA::IntelMP::IOAPIC(this); 343} 344 345Addr 346X86ISA::IntelMP::IntAssignment::writeOut( 347 PortProxy& proxy, Addr addr, uint8_t &checkSum) 348{ 349 BaseConfigEntry::writeOut(proxy, addr, checkSum); 350 checkSum += writeOutField(proxy, addr + 1, interruptType); 351 checkSum += writeOutField(proxy, addr + 2, flags); 352 checkSum += writeOutField(proxy, addr + 4, sourceBusID); 353 checkSum += writeOutField(proxy, addr + 5, sourceBusIRQ); 354 checkSum += writeOutField(proxy, addr + 6, destApicID); 355 checkSum += writeOutField(proxy, addr + 7, destApicIntIn); 356 return 8; 357} 358 359X86ISA::IntelMP::IOIntAssignment::IOIntAssignment(Params * p) : 360 IntAssignment(p, p->interrupt_type, p->polarity, p->trigger, 3, 361 p->source_bus_id, p->source_bus_irq, 362 p->dest_io_apic_id, p->dest_io_apic_intin) 363{} 364 365X86ISA::IntelMP::IOIntAssignment * 366X86IntelMPIOIntAssignmentParams::create() 367{ 368 return new X86ISA::IntelMP::IOIntAssignment(this); 369} 370 371X86ISA::IntelMP::LocalIntAssignment::LocalIntAssignment(Params * p) : 372 IntAssignment(p, p->interrupt_type, p->polarity, p->trigger, 4, 373 p->source_bus_id, p->source_bus_irq, 374 p->dest_local_apic_id, p->dest_local_apic_intin) 375{} 376 377X86ISA::IntelMP::LocalIntAssignment * 378X86IntelMPLocalIntAssignmentParams::create() 379{ 380 return new X86ISA::IntelMP::LocalIntAssignment(this); 381} 382 383Addr 384X86ISA::IntelMP::AddrSpaceMapping::writeOut( 385 PortProxy& proxy, Addr addr, uint8_t &checkSum) 386{ 387 ExtConfigEntry::writeOut(proxy, addr, checkSum); 388 checkSum += writeOutField(proxy, addr + 2, busID); 389 checkSum += writeOutField(proxy, addr + 3, addrType); 390 checkSum += writeOutField(proxy, addr + 4, addr); 391 checkSum += writeOutField(proxy, addr + 12, addrLength); 392 return length; 393} 394 395X86ISA::IntelMP::AddrSpaceMapping::AddrSpaceMapping(Params * p) : 396 ExtConfigEntry(p, 128, 20), 397 busID(p->bus_id), addrType(p->address_type), 398 addr(p->address), addrLength(p->length) 399{} 400 401X86ISA::IntelMP::AddrSpaceMapping * 402X86IntelMPAddrSpaceMappingParams::create() 403{ 404 return new X86ISA::IntelMP::AddrSpaceMapping(this); 405} 406 407Addr 408X86ISA::IntelMP::BusHierarchy::writeOut( 409 PortProxy& proxy, Addr addr, uint8_t &checkSum) 410{ 411 ExtConfigEntry::writeOut(proxy, addr, checkSum); 412 checkSum += writeOutField(proxy, addr + 2, busID); 413 checkSum += writeOutField(proxy, addr + 3, info); 414 checkSum += writeOutField(proxy, addr + 4, parentBus); 415 416 uint32_t reserved = 0; 417 proxy.writeBlob(addr + 5, (uint8_t *)(&reserved), 3); 418 419 return length; 420} 421 422X86ISA::IntelMP::BusHierarchy::BusHierarchy(Params * p) : 423 ExtConfigEntry(p, 129, 8), 424 busID(p->bus_id), info(0), parentBus(p->parent_bus) 425{ 426 if (p->subtractive_decode) 427 info |= 1; 428} 429 430X86ISA::IntelMP::BusHierarchy * 431X86IntelMPBusHierarchyParams::create() 432{ 433 return new X86ISA::IntelMP::BusHierarchy(this); 434} 435 436Addr 437X86ISA::IntelMP::CompatAddrSpaceMod::writeOut( 438 PortProxy& proxy, Addr addr, uint8_t &checkSum) 439{ 440 ExtConfigEntry::writeOut(proxy, addr, checkSum); 441 checkSum += writeOutField(proxy, addr + 2, busID); 442 checkSum += writeOutField(proxy, addr + 3, mod); 443 checkSum += writeOutField(proxy, addr + 4, rangeList); 444 return length; 445} 446 447X86ISA::IntelMP::CompatAddrSpaceMod::CompatAddrSpaceMod(Params * p) : 448 ExtConfigEntry(p, 130, 8), 449 busID(p->bus_id), mod(0), rangeList(p->range_list) 450{ 451 if (p->add) 452 mod |= 1; 453} 454 455X86ISA::IntelMP::CompatAddrSpaceMod * 456X86IntelMPCompatAddrSpaceModParams::create() 457{ 458 return new X86ISA::IntelMP::CompatAddrSpaceMod(this); 459} 460