intelmp.cc revision 8737
1/* 2 * Copyright (c) 2008 The Hewlett-Packard Development Company 3 * All rights reserved. 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Gabe Black 38 */ 39 40#include "arch/x86/bios/intelmp.hh" 41#include "arch/x86/isa_traits.hh" 42#include "base/misc.hh" 43#include "base/types.hh" 44#include "mem/port_proxy.hh" 45#include "sim/byteswap.hh" 46 47// Config entry types 48#include "params/X86IntelMPBaseConfigEntry.hh" 49#include "params/X86IntelMPExtConfigEntry.hh" 50 51// General table structures 52#include "params/X86IntelMPConfigTable.hh" 53#include "params/X86IntelMPFloatingPointer.hh" 54 55// Base entry types 56#include "params/X86IntelMPBus.hh" 57#include "params/X86IntelMPIOAPIC.hh" 58#include "params/X86IntelMPIOIntAssignment.hh" 59#include "params/X86IntelMPLocalIntAssignment.hh" 60#include "params/X86IntelMPProcessor.hh" 61 62// Extended entry types 63#include "params/X86IntelMPAddrSpaceMapping.hh" 64#include "params/X86IntelMPBusHierarchy.hh" 65#include "params/X86IntelMPCompatAddrSpaceMod.hh" 66 67using namespace std; 68 69const char X86ISA::IntelMP::FloatingPointer::signature[] = "_MP_"; 70 71template<class T> 72uint8_t 73writeOutField(PortProxy* proxy, Addr addr, T val) 74{ 75 uint64_t guestVal = X86ISA::htog(val); 76 proxy->writeBlob(addr, (uint8_t *)(&guestVal), sizeof(T)); 77 78 uint8_t checkSum = 0; 79 while(guestVal) { 80 checkSum += guestVal; 81 guestVal >>= 8; 82 } 83 return checkSum; 84} 85 86uint8_t 87writeOutString(PortProxy* proxy, Addr addr, string str, int length) 88{ 89 char cleanedString[length + 1]; 90 cleanedString[length] = 0; 91 92 if (str.length() > length) { 93 memcpy(cleanedString, str.c_str(), length); 94 warn("Intel MP configuration table string \"%s\" " 95 "will be truncated to \"%s\".\n", str, cleanedString); 96 } else { 97 memcpy(cleanedString, str.c_str(), str.length()); 98 memset(cleanedString + str.length(), 0, length - str.length()); 99 } 100 proxy->writeBlob(addr, (uint8_t *)(&cleanedString), length); 101 102 uint8_t checkSum = 0; 103 for (int i = 0; i < length; i++) 104 checkSum += cleanedString[i]; 105 106 return checkSum; 107} 108 109Addr 110X86ISA::IntelMP::FloatingPointer::writeOut(PortProxy* proxy, Addr addr) 111{ 112 // Make sure that either a config table is present or a default 113 // configuration was found but not both. 114 if (!tableAddr && !defaultConfig) 115 fatal("Either an MP configuration table or a default configuration " 116 "must be used."); 117 if (tableAddr && defaultConfig) 118 fatal("Both an MP configuration table and a default configuration " 119 "were set."); 120 121 uint8_t checkSum = 0; 122 123 proxy->writeBlob(addr, (uint8_t *)signature, 4); 124 for (int i = 0; i < 4; i++) 125 checkSum += signature[i]; 126 127 checkSum += writeOutField(proxy, addr + 4, tableAddr); 128 129 // The length of the structure in paragraphs, aka 16 byte chunks. 130 uint8_t length = 1; 131 proxy->writeBlob(addr + 8, &length, 1); 132 checkSum += length; 133 134 proxy->writeBlob(addr + 9, &specRev, 1); 135 checkSum += specRev; 136 137 proxy->writeBlob(addr + 11, &defaultConfig, 1); 138 checkSum += defaultConfig; 139 140 uint32_t features2_5 = imcrPresent ? (1 << 7) : 0; 141 checkSum += writeOutField(proxy, addr + 12, features2_5); 142 143 checkSum = -checkSum; 144 proxy->writeBlob(addr + 10, &checkSum, 1); 145 146 return 16; 147} 148 149X86ISA::IntelMP::FloatingPointer::FloatingPointer(Params * p) : 150 SimObject(p), tableAddr(0), specRev(p->spec_rev), 151 defaultConfig(p->default_config), imcrPresent(p->imcr_present) 152{} 153 154X86ISA::IntelMP::FloatingPointer * 155X86IntelMPFloatingPointerParams::create() 156{ 157 return new X86ISA::IntelMP::FloatingPointer(this); 158} 159 160Addr 161X86ISA::IntelMP::BaseConfigEntry::writeOut(PortProxy* proxy, 162 Addr addr, uint8_t &checkSum) 163{ 164 proxy->writeBlob(addr, &type, 1); 165 checkSum += type; 166 return 1; 167} 168 169X86ISA::IntelMP::BaseConfigEntry::BaseConfigEntry(Params * p, uint8_t _type) : 170 SimObject(p), type(_type) 171{} 172 173Addr 174X86ISA::IntelMP::ExtConfigEntry::writeOut(PortProxy* proxy, 175 Addr addr, uint8_t &checkSum) 176{ 177 proxy->writeBlob(addr, &type, 1); 178 checkSum += type; 179 proxy->writeBlob(addr + 1, &length, 1); 180 checkSum += length; 181 return 1; 182} 183 184X86ISA::IntelMP::ExtConfigEntry::ExtConfigEntry(Params * p, 185 uint8_t _type, uint8_t _length) : 186 SimObject(p), type(_type), length(_length) 187{} 188 189const char X86ISA::IntelMP::ConfigTable::signature[] = "PCMP"; 190 191Addr 192X86ISA::IntelMP::ConfigTable::writeOut(PortProxy* proxy, Addr addr) 193{ 194 uint8_t checkSum = 0; 195 196 proxy->writeBlob(addr, (uint8_t *)signature, 4); 197 for (int i = 0; i < 4; i++) 198 checkSum += signature[i]; 199 200 // Base table length goes here but will be calculated later. 201 202 proxy->writeBlob(addr + 6, (uint8_t *)(&specRev), 1); 203 checkSum += specRev; 204 205 // The checksum goes here but is still being calculated. 206 207 checkSum += writeOutString(proxy, addr + 8, oemID, 8); 208 checkSum += writeOutString(proxy, addr + 16, productID, 12); 209 210 checkSum += writeOutField(proxy, addr + 28, oemTableAddr); 211 checkSum += writeOutField(proxy, addr + 32, oemTableSize); 212 checkSum += writeOutField(proxy, addr + 34, (uint16_t)baseEntries.size()); 213 checkSum += writeOutField(proxy, addr + 36, localApic); 214 215 uint8_t reserved = 0; 216 proxy->writeBlob(addr + 43, &reserved, 1); 217 checkSum += reserved; 218 219 vector<BaseConfigEntry *>::iterator baseEnt; 220 uint16_t offset = 44; 221 for (baseEnt = baseEntries.begin(); 222 baseEnt != baseEntries.end(); baseEnt++) { 223 offset += (*baseEnt)->writeOut(proxy, addr + offset, checkSum); 224 } 225 226 // We've found the end of the base table this point. 227 checkSum += writeOutField(proxy, addr + 4, offset); 228 229 vector<ExtConfigEntry *>::iterator extEnt; 230 uint16_t extOffset = 0; 231 uint8_t extCheckSum = 0; 232 for (extEnt = extEntries.begin(); 233 extEnt != extEntries.end(); extEnt++) { 234 extOffset += (*extEnt)->writeOut(proxy, 235 addr + offset + extOffset, extCheckSum); 236 } 237 238 checkSum += writeOutField(proxy, addr + 40, extOffset); 239 extCheckSum = -extCheckSum; 240 checkSum += writeOutField(proxy, addr + 42, extCheckSum); 241 242 // And now, we finally have the whole check sum completed. 243 checkSum = -checkSum; 244 writeOutField(proxy, addr + 7, checkSum); 245 246 return offset + extOffset; 247}; 248 249X86ISA::IntelMP::ConfigTable::ConfigTable(Params * p) : SimObject(p), 250 specRev(p->spec_rev), oemID(p->oem_id), productID(p->product_id), 251 oemTableAddr(p->oem_table_addr), oemTableSize(p->oem_table_size), 252 localApic(p->local_apic), 253 baseEntries(p->base_entries), extEntries(p->ext_entries) 254{} 255 256X86ISA::IntelMP::ConfigTable * 257X86IntelMPConfigTableParams::create() 258{ 259 return new X86ISA::IntelMP::ConfigTable(this); 260} 261 262Addr 263X86ISA::IntelMP::Processor::writeOut( 264 PortProxy* proxy, Addr addr, uint8_t &checkSum) 265{ 266 BaseConfigEntry::writeOut(proxy, addr, checkSum); 267 checkSum += writeOutField(proxy, addr + 1, localApicID); 268 checkSum += writeOutField(proxy, addr + 2, localApicVersion); 269 checkSum += writeOutField(proxy, addr + 3, cpuFlags); 270 checkSum += writeOutField(proxy, addr + 4, cpuSignature); 271 checkSum += writeOutField(proxy, addr + 8, featureFlags); 272 273 uint32_t reserved = 0; 274 proxy->writeBlob(addr + 12, (uint8_t *)(&reserved), 4); 275 proxy->writeBlob(addr + 16, (uint8_t *)(&reserved), 4); 276 return 20; 277} 278 279X86ISA::IntelMP::Processor::Processor(Params * p) : BaseConfigEntry(p, 0), 280 localApicID(p->local_apic_id), localApicVersion(p->local_apic_version), 281 cpuFlags(0), cpuSignature(0), featureFlags(p->feature_flags) 282{ 283 if (p->enable) 284 cpuFlags |= (1 << 0); 285 if (p->bootstrap) 286 cpuFlags |= (1 << 1); 287 288 replaceBits(cpuSignature, 0, 3, p->stepping); 289 replaceBits(cpuSignature, 4, 7, p->model); 290 replaceBits(cpuSignature, 8, 11, p->family); 291} 292 293X86ISA::IntelMP::Processor * 294X86IntelMPProcessorParams::create() 295{ 296 return new X86ISA::IntelMP::Processor(this); 297} 298 299Addr 300X86ISA::IntelMP::Bus::writeOut( 301 PortProxy* proxy, Addr addr, uint8_t &checkSum) 302{ 303 BaseConfigEntry::writeOut(proxy, addr, checkSum); 304 checkSum += writeOutField(proxy, addr + 1, busID); 305 checkSum += writeOutString(proxy, addr + 2, busType, 6); 306 return 8; 307} 308 309X86ISA::IntelMP::Bus::Bus(Params * p) : BaseConfigEntry(p, 1), 310 busID(p->bus_id), busType(p->bus_type) 311{} 312 313X86ISA::IntelMP::Bus * 314X86IntelMPBusParams::create() 315{ 316 return new X86ISA::IntelMP::Bus(this); 317} 318 319Addr 320X86ISA::IntelMP::IOAPIC::writeOut( 321 PortProxy* proxy, Addr addr, uint8_t &checkSum) 322{ 323 BaseConfigEntry::writeOut(proxy, addr, checkSum); 324 checkSum += writeOutField(proxy, addr + 1, id); 325 checkSum += writeOutField(proxy, addr + 2, version); 326 checkSum += writeOutField(proxy, addr + 3, flags); 327 checkSum += writeOutField(proxy, addr + 4, address); 328 return 8; 329} 330 331X86ISA::IntelMP::IOAPIC::IOAPIC(Params * p) : BaseConfigEntry(p, 2), 332 id(p->id), version(p->version), flags(0), address(p->address) 333{ 334 if (p->enable) 335 flags |= 1; 336} 337 338X86ISA::IntelMP::IOAPIC * 339X86IntelMPIOAPICParams::create() 340{ 341 return new X86ISA::IntelMP::IOAPIC(this); 342} 343 344Addr 345X86ISA::IntelMP::IntAssignment::writeOut( 346 PortProxy* proxy, Addr addr, uint8_t &checkSum) 347{ 348 BaseConfigEntry::writeOut(proxy, addr, checkSum); 349 checkSum += writeOutField(proxy, addr + 1, interruptType); 350 checkSum += writeOutField(proxy, addr + 2, flags); 351 checkSum += writeOutField(proxy, addr + 4, sourceBusID); 352 checkSum += writeOutField(proxy, addr + 5, sourceBusIRQ); 353 checkSum += writeOutField(proxy, addr + 6, destApicID); 354 checkSum += writeOutField(proxy, addr + 7, destApicIntIn); 355 return 8; 356} 357 358X86ISA::IntelMP::IOIntAssignment::IOIntAssignment(Params * p) : 359 IntAssignment(p, p->interrupt_type, p->polarity, p->trigger, 3, 360 p->source_bus_id, p->source_bus_irq, 361 p->dest_io_apic_id, p->dest_io_apic_intin) 362{} 363 364X86ISA::IntelMP::IOIntAssignment * 365X86IntelMPIOIntAssignmentParams::create() 366{ 367 return new X86ISA::IntelMP::IOIntAssignment(this); 368} 369 370X86ISA::IntelMP::LocalIntAssignment::LocalIntAssignment(Params * p) : 371 IntAssignment(p, p->interrupt_type, p->polarity, p->trigger, 4, 372 p->source_bus_id, p->source_bus_irq, 373 p->dest_local_apic_id, p->dest_local_apic_intin) 374{} 375 376X86ISA::IntelMP::LocalIntAssignment * 377X86IntelMPLocalIntAssignmentParams::create() 378{ 379 return new X86ISA::IntelMP::LocalIntAssignment(this); 380} 381 382Addr 383X86ISA::IntelMP::AddrSpaceMapping::writeOut( 384 PortProxy* proxy, Addr addr, uint8_t &checkSum) 385{ 386 ExtConfigEntry::writeOut(proxy, addr, checkSum); 387 checkSum += writeOutField(proxy, addr + 2, busID); 388 checkSum += writeOutField(proxy, addr + 3, addrType); 389 checkSum += writeOutField(proxy, addr + 4, addr); 390 checkSum += writeOutField(proxy, addr + 12, addrLength); 391 return length; 392} 393 394X86ISA::IntelMP::AddrSpaceMapping::AddrSpaceMapping(Params * p) : 395 ExtConfigEntry(p, 128, 20), 396 busID(p->bus_id), addrType(p->address_type), 397 addr(p->address), addrLength(p->length) 398{} 399 400X86ISA::IntelMP::AddrSpaceMapping * 401X86IntelMPAddrSpaceMappingParams::create() 402{ 403 return new X86ISA::IntelMP::AddrSpaceMapping(this); 404} 405 406Addr 407X86ISA::IntelMP::BusHierarchy::writeOut( 408 PortProxy* proxy, Addr addr, uint8_t &checkSum) 409{ 410 ExtConfigEntry::writeOut(proxy, addr, checkSum); 411 checkSum += writeOutField(proxy, addr + 2, busID); 412 checkSum += writeOutField(proxy, addr + 3, info); 413 checkSum += writeOutField(proxy, addr + 4, parentBus); 414 415 uint32_t reserved = 0; 416 proxy->writeBlob(addr + 5, (uint8_t *)(&reserved), 3); 417 418 return length; 419} 420 421X86ISA::IntelMP::BusHierarchy::BusHierarchy(Params * p) : 422 ExtConfigEntry(p, 129, 8), 423 busID(p->bus_id), info(0), parentBus(p->parent_bus) 424{ 425 if (p->subtractive_decode) 426 info |= 1; 427} 428 429X86ISA::IntelMP::BusHierarchy * 430X86IntelMPBusHierarchyParams::create() 431{ 432 return new X86ISA::IntelMP::BusHierarchy(this); 433} 434 435Addr 436X86ISA::IntelMP::CompatAddrSpaceMod::writeOut( 437 PortProxy* proxy, Addr addr, uint8_t &checkSum) 438{ 439 ExtConfigEntry::writeOut(proxy, addr, checkSum); 440 checkSum += writeOutField(proxy, addr + 2, busID); 441 checkSum += writeOutField(proxy, addr + 3, mod); 442 checkSum += writeOutField(proxy, addr + 4, rangeList); 443 return length; 444} 445 446X86ISA::IntelMP::CompatAddrSpaceMod::CompatAddrSpaceMod(Params * p) : 447 ExtConfigEntry(p, 130, 8), 448 busID(p->bus_id), mod(0), rangeList(p->range_list) 449{ 450 if (p->add) 451 mod |= 1; 452} 453 454X86ISA::IntelMP::CompatAddrSpaceMod * 455X86IntelMPCompatAddrSpaceModParams::create() 456{ 457 return new X86ISA::IntelMP::CompatAddrSpaceMod(this); 458} 459