tsunami_pchip.cc revision 2542
15882Snate@binkert.org/* 25882Snate@binkert.org * Copyright (c) 2004-2005 The Regents of The University of Michigan 35882Snate@binkert.org * All rights reserved. 45882Snate@binkert.org * 55882Snate@binkert.org * Redistribution and use in source and binary forms, with or without 65882Snate@binkert.org * modification, are permitted provided that the following conditions are 75882Snate@binkert.org * met: redistributions of source code must retain the above copyright 85882Snate@binkert.org * notice, this list of conditions and the following disclaimer; 95882Snate@binkert.org * redistributions in binary form must reproduce the above copyright 105882Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 115882Snate@binkert.org * documentation and/or other materials provided with the distribution; 125882Snate@binkert.org * neither the name of the copyright holders nor the names of its 135882Snate@binkert.org * contributors may be used to endorse or promote products derived from 145882Snate@binkert.org * this software without specific prior written permission. 155882Snate@binkert.org * 165882Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175882Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185882Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195882Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205882Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215882Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225882Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235882Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245882Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255882Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265882Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275882Snate@binkert.org */ 285882Snate@binkert.org 295882Snate@binkert.org/** @file 305882Snate@binkert.org * Tsunami PChip (pci) 3111793Sbrandon.potter@amd.com */ 3211793Sbrandon.potter@amd.com 335882Snate@binkert.org#include <deque> 345882Snate@binkert.org#include <string> 355882Snate@binkert.org#include <vector> 368232Snate@binkert.org 378229Snate@binkert.org#include "base/trace.hh" 388229Snate@binkert.org#include "dev/tsunami_pchip.hh" 395882Snate@binkert.org#include "dev/tsunamireg.h" 4012334Sgabeblack@google.com#include "dev/tsunami.hh" 418232Snate@binkert.org#include "mem/packet.hh" 428232Snate@binkert.org#include "sim/builder.hh" 435882Snate@binkert.org#include "sim/system.hh" 448231Snate@binkert.org 458231Snate@binkert.orgusing namespace std; 468232Snate@binkert.org//Should this be AlphaISA? 478232Snate@binkert.orgusing namespace TheISA; 488232Snate@binkert.org 498232Snate@binkert.orgTsunamiPChip::TsunamiPChip(Params *p) 508232Snate@binkert.org: BasicPioDevice(p) 515882Snate@binkert.org{ 528231Snate@binkert.org pioSize = 0xfff; 535882Snate@binkert.org 545882Snate@binkert.org for (int i = 0; i < 4; i++) { 555882Snate@binkert.org wsba[i] = 0; 565882Snate@binkert.org wsm[i] = 0; 578231Snate@binkert.org tba[i] = 0; 585882Snate@binkert.org } 595882Snate@binkert.org 608231Snate@binkert.org // initialize pchip control register 618232Snate@binkert.org pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); 628232Snate@binkert.org 638232Snate@binkert.org //Set back pointer in tsunami 648232Snate@binkert.org p->tsunami->pchip = this; 658232Snate@binkert.org} 668232Snate@binkert.org 678232Snate@binkert.orgTick 688232Snate@binkert.orgTsunamiPChip::read(Packet &pkt) 698232Snate@binkert.org{ 708232Snate@binkert.org assert(pkt.result == Unknown); 718232Snate@binkert.org assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); 7211153SCurtis.Dunham@arm.com 7311153SCurtis.Dunham@arm.com pkt.time = curTick + pioDelay; 748232Snate@binkert.org Addr daddr = pkt.addr - pioAddr; 758232Snate@binkert.org 768232Snate@binkert.org uint64_t *data64; 778232Snate@binkert.org 788232Snate@binkert.org if (!pkt.data) { 798232Snate@binkert.org data64 = new uint64_t; 808232Snate@binkert.org pkt.data = (uint8_t*)data64; 818232Snate@binkert.org } else 828232Snate@binkert.org data64 = (uint64_t*)pkt.data; 838232Snate@binkert.org 848232Snate@binkert.org DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt.addr, pkt.size); 858232Snate@binkert.org 868232Snate@binkert.org switch(daddr) { 878232Snate@binkert.org case TSDEV_PC_WSBA0: 888232Snate@binkert.org *data64 = wsba[0]; 898232Snate@binkert.org break; 908232Snate@binkert.org case TSDEV_PC_WSBA1: 918232Snate@binkert.org *data64 = wsba[1]; 928232Snate@binkert.org break; 938232Snate@binkert.org case TSDEV_PC_WSBA2: 948232Snate@binkert.org *data64 = wsba[2]; 958232Snate@binkert.org break; 968232Snate@binkert.org case TSDEV_PC_WSBA3: 978232Snate@binkert.org *data64 = wsba[3]; 988232Snate@binkert.org break; 998232Snate@binkert.org case TSDEV_PC_WSM0: 1008232Snate@binkert.org *data64 = wsm[0]; 10111153SCurtis.Dunham@arm.com break; 10211153SCurtis.Dunham@arm.com case TSDEV_PC_WSM1: 10311153SCurtis.Dunham@arm.com *data64 = wsm[1]; 10411153SCurtis.Dunham@arm.com break; 10511153SCurtis.Dunham@arm.com case TSDEV_PC_WSM2: 10611153SCurtis.Dunham@arm.com *data64 = wsm[2]; 10711153SCurtis.Dunham@arm.com break; 10811153SCurtis.Dunham@arm.com case TSDEV_PC_WSM3: 10911153SCurtis.Dunham@arm.com *data64 = wsm[3]; 11011153SCurtis.Dunham@arm.com break; 11111153SCurtis.Dunham@arm.com case TSDEV_PC_TBA0: 11211153SCurtis.Dunham@arm.com *data64 = tba[0]; 11311153SCurtis.Dunham@arm.com break; 11411153SCurtis.Dunham@arm.com case TSDEV_PC_TBA1: 11511153SCurtis.Dunham@arm.com *data64 = tba[1]; 11611153SCurtis.Dunham@arm.com break; 1178232Snate@binkert.org case TSDEV_PC_TBA2: 1188232Snate@binkert.org *data64 = tba[2]; 11911153SCurtis.Dunham@arm.com break; 12011153SCurtis.Dunham@arm.com case TSDEV_PC_TBA3: 1218232Snate@binkert.org *data64 = tba[3]; 1228232Snate@binkert.org break; 1238232Snate@binkert.org case TSDEV_PC_PCTL: 1248232Snate@binkert.org *data64 = pctl; 1258232Snate@binkert.org break; 12611153SCurtis.Dunham@arm.com case TSDEV_PC_PLAT: 12711153SCurtis.Dunham@arm.com panic("PC_PLAT not implemented\n"); 1288232Snate@binkert.org case TSDEV_PC_RES: 1298232Snate@binkert.org panic("PC_RES not implemented\n"); 1308232Snate@binkert.org case TSDEV_PC_PERROR: 1318232Snate@binkert.org *data64 = 0x00; 1328232Snate@binkert.org break; 1338232Snate@binkert.org case TSDEV_PC_PERRMASK: 1348232Snate@binkert.org *data64 = 0x00; 1358232Snate@binkert.org break; 1368232Snate@binkert.org case TSDEV_PC_PERRSET: 1378232Snate@binkert.org panic("PC_PERRSET not implemented\n"); 1388232Snate@binkert.org case TSDEV_PC_TLBIV: 1398232Snate@binkert.org panic("PC_TLBIV not implemented\n"); 1408232Snate@binkert.org case TSDEV_PC_TLBIA: 1418232Snate@binkert.org *data64 = 0x00; // shouldn't be readable, but linux 1428232Snate@binkert.org break; 1438232Snate@binkert.org case TSDEV_PC_PMONCTL: 1448232Snate@binkert.org panic("PC_PMONCTL not implemented\n"); 1458232Snate@binkert.org case TSDEV_PC_PMONCNT: 1468232Snate@binkert.org panic("PC_PMONCTN not implemented\n"); 1478232Snate@binkert.org default: 1488232Snate@binkert.org panic("Default in PChip Read reached reading 0x%x\n", daddr); 1498232Snate@binkert.org } 1508232Snate@binkert.org pkt.result = Success; 1518232Snate@binkert.org return pioDelay; 1528232Snate@binkert.org 1538699Ssteve.reinhardt@amd.com} 1548232Snate@binkert.org 1558232Snate@binkert.orgTick 1568232Snate@binkert.orgTsunamiPChip::write(Packet &pkt) 1578232Snate@binkert.org{ 1588232Snate@binkert.org pkt.time = curTick + pioDelay; 1598232Snate@binkert.org 1608232Snate@binkert.org assert(pkt.result == Unknown); 1618232Snate@binkert.org assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize); 1628232Snate@binkert.org Addr daddr = pkt.addr - pioAddr; 1638232Snate@binkert.org 1648232Snate@binkert.org uint64_t data64 = *(uint64_t *)pkt.data; 1658232Snate@binkert.org assert(pkt.size == sizeof(uint64_t)); 1668232Snate@binkert.org 1678232Snate@binkert.org DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt.addr, pkt.size); 1688232Snate@binkert.org 1698232Snate@binkert.org switch(daddr) { 1708232Snate@binkert.org case TSDEV_PC_WSBA0: 1718232Snate@binkert.org wsba[0] = data64; 1728232Snate@binkert.org break; 1738232Snate@binkert.org case TSDEV_PC_WSBA1: 1748232Snate@binkert.org wsba[1] = data64; 1758231Snate@binkert.org break; 1768232Snate@binkert.org case TSDEV_PC_WSBA2: 1778232Snate@binkert.org wsba[2] = data64; 1788232Snate@binkert.org break; 1798232Snate@binkert.org case TSDEV_PC_WSBA3: 1808232Snate@binkert.org wsba[3] = data64; 1818232Snate@binkert.org break; 1828232Snate@binkert.org case TSDEV_PC_WSM0: 1838232Snate@binkert.org wsm[0] = data64; 1848232Snate@binkert.org break; 1858232Snate@binkert.org case TSDEV_PC_WSM1: 1868232Snate@binkert.org wsm[1] = data64; 1878232Snate@binkert.org break; 1888232Snate@binkert.org case TSDEV_PC_WSM2: 1898232Snate@binkert.org wsm[2] = data64; 1908232Snate@binkert.org break; 1918232Snate@binkert.org case TSDEV_PC_WSM3: 1928232Snate@binkert.org wsm[3] = data64; 1938232Snate@binkert.org break; 1948232Snate@binkert.org case TSDEV_PC_TBA0: 1958232Snate@binkert.org tba[0] = data64; 1968232Snate@binkert.org break; 1978232Snate@binkert.org case TSDEV_PC_TBA1: 1988232Snate@binkert.org tba[1] = data64; 1998232Snate@binkert.org break; 2008232Snate@binkert.org case TSDEV_PC_TBA2: 2018232Snate@binkert.org tba[2] = data64; 202 break; 203 case TSDEV_PC_TBA3: 204 tba[3] = data64; 205 break; 206 case TSDEV_PC_PCTL: 207 pctl = data64; 208 break; 209 case TSDEV_PC_PLAT: 210 panic("PC_PLAT not implemented\n"); 211 case TSDEV_PC_RES: 212 panic("PC_RES not implemented\n"); 213 case TSDEV_PC_PERROR: 214 break; 215 case TSDEV_PC_PERRMASK: 216 panic("PC_PERRMASK not implemented\n"); 217 case TSDEV_PC_PERRSET: 218 panic("PC_PERRSET not implemented\n"); 219 case TSDEV_PC_TLBIV: 220 panic("PC_TLBIV not implemented\n"); 221 case TSDEV_PC_TLBIA: 222 break; // value ignored, supposted to invalidate SG TLB 223 case TSDEV_PC_PMONCTL: 224 panic("PC_PMONCTL not implemented\n"); 225 case TSDEV_PC_PMONCNT: 226 panic("PC_PMONCTN not implemented\n"); 227 default: 228 panic("Default in PChip Read reached reading 0x%x\n", daddr); 229 230 } // uint64_t 231 232 pkt.result = Success; 233 return pioDelay; 234} 235 236#define DMA_ADDR_MASK ULL(0x3ffffffff) 237 238Addr 239TsunamiPChip::translatePciToDma(Addr busAddr) 240{ 241 // compare the address to the window base registers 242 uint64_t tbaMask = 0; 243 uint64_t baMask = 0; 244 245 uint64_t windowMask = 0; 246 uint64_t windowBase = 0; 247 248 uint64_t pteEntry = 0; 249 250 Addr pteAddr; 251 Addr dmaAddr; 252 253#if 0 254 DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); 255 for (int i = 0; i < 4; i++) { 256 DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", 257 i, wsba[i], wsm[i]); 258 259 windowBase = wsba[i]; 260 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 261 262 if ((busAddr & windowMask) == (windowBase & windowMask)) { 263 DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", 264 i, windowBase, windowMask, (busAddr & windowMask), 265 (windowBase & windowMask)); 266 } 267 } 268#endif 269 270 for (int i = 0; i < 4; i++) { 271 272 windowBase = wsba[i]; 273 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 274 275 if ((busAddr & windowMask) == (windowBase & windowMask)) { 276 277 if (wsba[i] & 0x1) { // see if enabled 278 if (wsba[i] & 0x2) { // see if SG bit is set 279 /** @todo 280 This currently is faked by just doing a direct 281 read from memory, however, to be realistic, this 282 needs to actually do a bus transaction. The process 283 is explained in the tsunami documentation on page 284 10-12 and basically munges the address to look up a 285 PTE from a table in memory and then uses that mapping 286 to create an address for the SG page 287 */ 288 289 tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); 290 baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); 291 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 292 293 pioPort->readBlob(pteAddr, (uint8_t*)&pteEntry, sizeof(uint64_t)); 294 295 dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); 296 297 } else { 298 baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); 299 tbaMask = ~baMask; 300 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 301 } 302 303 return (dmaAddr & DMA_ADDR_MASK); 304 } 305 } 306 } 307 308 // if no match was found, then return the original address 309 return busAddr; 310} 311 312void 313TsunamiPChip::serialize(std::ostream &os) 314{ 315 SERIALIZE_SCALAR(pctl); 316 SERIALIZE_ARRAY(wsba, 4); 317 SERIALIZE_ARRAY(wsm, 4); 318 SERIALIZE_ARRAY(tba, 4); 319} 320 321void 322TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 323{ 324 UNSERIALIZE_SCALAR(pctl); 325 UNSERIALIZE_ARRAY(wsba, 4); 326 UNSERIALIZE_ARRAY(wsm, 4); 327 UNSERIALIZE_ARRAY(tba, 4); 328} 329 330 331BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 332 333 Param<Addr> pio_addr; 334 Param<Tick> pio_latency; 335 SimObjectParam<Platform *> platform; 336 SimObjectParam<System *> system; 337 SimObjectParam<Tsunami *> tsunami; 338 339END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 340 341BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 342 343 INIT_PARAM(pio_addr, "Device Address"), 344 INIT_PARAM(pio_latency, "Programmed IO latency"), 345 INIT_PARAM(platform, "platform"), 346 INIT_PARAM(system, "system object"), 347 INIT_PARAM(tsunami, "Tsunami") 348 349END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 350 351CREATE_SIM_OBJECT(TsunamiPChip) 352{ 353 TsunamiPChip::Params *p = new TsunamiPChip::Params; 354 p->name = getInstanceName(); 355 p->pio_addr = pio_addr; 356 p->pio_delay = pio_latency; 357 p->platform = platform; 358 p->system = system; 359 p->tsunami = tsunami; 360 return new TsunamiPChip(p); 361} 362 363REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) 364