tsunami_pchip.cc revision 9808:13ffc0066b76
11689SN/A/* 21689SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 39915Ssteve.reinhardt@amd.com * All rights reserved. 41689SN/A * 51689SN/A * Redistribution and use in source and binary forms, with or without 61689SN/A * modification, are permitted provided that the following conditions are 71689SN/A * met: redistributions of source code must retain the above copyright 81689SN/A * notice, this list of conditions and the following disclaimer; 91689SN/A * redistributions in binary form must reproduce the above copyright 101689SN/A * notice, this list of conditions and the following disclaimer in the 111689SN/A * documentation and/or other materials provided with the distribution; 121689SN/A * neither the name of the copyright holders nor the names of its 131689SN/A * contributors may be used to endorse or promote products derived from 141689SN/A * this software without specific prior written permission. 151689SN/A * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271689SN/A * 282665Ssaidi@eecs.umich.edu * Authors: Ali Saidi 292665Ssaidi@eecs.umich.edu * Andrew Schultz 302665Ssaidi@eecs.umich.edu */ 311689SN/A 321689SN/A/** @file 332292SN/A * Tsunami PChip (pci) 342292SN/A */ 351060SN/A 366658Snate@binkert.org#include <deque> 376658Snate@binkert.org#include <string> 382165SN/A#include <vector> 398793Sgblack@eecs.umich.edu 402669Sktlim@umich.edu#include "base/trace.hh" 411681SN/A#include "config/the_isa.hh" 426658Snate@binkert.org#include "debug/Tsunami.hh" 431717SN/A#include "dev/alpha/tsunami.hh" 448232Snate@binkert.org#include "dev/alpha/tsunami_pchip.hh" 451060SN/A#include "dev/alpha/tsunamireg.h" 469919Ssteve.reinhardt@amd.com#include "mem/packet.hh" 479919Ssteve.reinhardt@amd.com#include "mem/packet_access.hh" 482292SN/A#include "sim/system.hh" 492292SN/A 502292SN/Ausing namespace std; 511060SN/A//Should this be AlphaISA? 521060SN/Ausing namespace TheISA; 539915Ssteve.reinhardt@amd.com 549915Ssteve.reinhardt@amd.comTsunamiPChip::TsunamiPChip(const Params *p) 552107SN/A : BasicPioDevice(p, 0x1000) 562107SN/A{ 572669Sktlim@umich.edu for (int i = 0; i < 4; i++) { 582159SN/A wsba[i] = 0; 592669Sktlim@umich.edu wsm[i] = 0; 602669Sktlim@umich.edu tba[i] = 0; 612669Sktlim@umich.edu } 622669Sktlim@umich.edu 631060SN/A // initialize pchip control register 649915Ssteve.reinhardt@amd.com pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); 659919Ssteve.reinhardt@amd.com 661060SN/A //Set back pointer in tsunami 679915Ssteve.reinhardt@amd.com p->tsunami->pchip = this; 689919Ssteve.reinhardt@amd.com} 699915Ssteve.reinhardt@amd.com 709915Ssteve.reinhardt@amd.comTick 719915Ssteve.reinhardt@amd.comTsunamiPChip::read(PacketPtr pkt) 729915Ssteve.reinhardt@amd.com{ 739915Ssteve.reinhardt@amd.com assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 749915Ssteve.reinhardt@amd.com 759915Ssteve.reinhardt@amd.com pkt->allocate(); 769915Ssteve.reinhardt@amd.com Addr daddr = (pkt->getAddr() - pioAddr) >> 6;; 779919Ssteve.reinhardt@amd.com assert(pkt->getSize() == sizeof(uint64_t)); 789919Ssteve.reinhardt@amd.com 799919Ssteve.reinhardt@amd.com 809919Ssteve.reinhardt@amd.com DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize()); 819919Ssteve.reinhardt@amd.com 829919Ssteve.reinhardt@amd.com switch(daddr) { 839915Ssteve.reinhardt@amd.com case TSDEV_PC_WSBA0: 849915Ssteve.reinhardt@amd.com pkt->set(wsba[0]); 859915Ssteve.reinhardt@amd.com break; 869915Ssteve.reinhardt@amd.com case TSDEV_PC_WSBA1: 879915Ssteve.reinhardt@amd.com pkt->set(wsba[1]); 889915Ssteve.reinhardt@amd.com break; 891060SN/A case TSDEV_PC_WSBA2: 902292SN/A pkt->set(wsba[2]); 912292SN/A break; 922292SN/A case TSDEV_PC_WSBA3: 932292SN/A pkt->set(wsba[3]); 949915Ssteve.reinhardt@amd.com break; 951060SN/A case TSDEV_PC_WSM0: 961060SN/A pkt->set(wsm[0]); 979086Sandreas.hansson@arm.com break; 989086Sandreas.hansson@arm.com case TSDEV_PC_WSM1: 999086Sandreas.hansson@arm.com pkt->set(wsm[1]); 1009919Ssteve.reinhardt@amd.com break; 1019919Ssteve.reinhardt@amd.com case TSDEV_PC_WSM2: 1029919Ssteve.reinhardt@amd.com pkt->set(wsm[2]); 1039919Ssteve.reinhardt@amd.com break; 1049086Sandreas.hansson@arm.com case TSDEV_PC_WSM3: 1059915Ssteve.reinhardt@amd.com pkt->set(wsm[3]); 1069915Ssteve.reinhardt@amd.com break; 1079915Ssteve.reinhardt@amd.com case TSDEV_PC_TBA0: 1089915Ssteve.reinhardt@amd.com pkt->set(tba[0]); 1099915Ssteve.reinhardt@amd.com break; 1109915Ssteve.reinhardt@amd.com case TSDEV_PC_TBA1: 1119915Ssteve.reinhardt@amd.com pkt->set(tba[1]); 1129915Ssteve.reinhardt@amd.com break; 1139915Ssteve.reinhardt@amd.com case TSDEV_PC_TBA2: 1149915Ssteve.reinhardt@amd.com pkt->set(tba[2]); 1159915Ssteve.reinhardt@amd.com break; 1169915Ssteve.reinhardt@amd.com case TSDEV_PC_TBA3: 1179915Ssteve.reinhardt@amd.com pkt->set(tba[3]); 1189915Ssteve.reinhardt@amd.com break; 1199915Ssteve.reinhardt@amd.com case TSDEV_PC_PCTL: 1209915Ssteve.reinhardt@amd.com pkt->set(pctl); 1219915Ssteve.reinhardt@amd.com break; 1229915Ssteve.reinhardt@amd.com case TSDEV_PC_PLAT: 1239915Ssteve.reinhardt@amd.com panic("PC_PLAT not implemented\n"); 1249915Ssteve.reinhardt@amd.com case TSDEV_PC_RES: 1259915Ssteve.reinhardt@amd.com panic("PC_RES not implemented\n"); 1269915Ssteve.reinhardt@amd.com case TSDEV_PC_PERROR: 1279915Ssteve.reinhardt@amd.com pkt->set((uint64_t)0x00); 1289915Ssteve.reinhardt@amd.com break; 1299915Ssteve.reinhardt@amd.com case TSDEV_PC_PERRMASK: 1309915Ssteve.reinhardt@amd.com pkt->set((uint64_t)0x00); 1319915Ssteve.reinhardt@amd.com break; 1321060SN/A case TSDEV_PC_PERRSET: 1332292SN/A panic("PC_PERRSET not implemented\n"); 1349915Ssteve.reinhardt@amd.com case TSDEV_PC_TLBIV: 1351060SN/A panic("PC_TLBIV not implemented\n"); 1369915Ssteve.reinhardt@amd.com case TSDEV_PC_TLBIA: 1371061SN/A pkt->set((uint64_t)0x00); // shouldn't be readable, but linux 1381060SN/A break; 1392690Sktlim@umich.edu case TSDEV_PC_PMONCTL: 1401060SN/A panic("PC_PMONCTL not implemented\n"); 1411060SN/A case TSDEV_PC_PMONCNT: 1421060SN/A panic("PC_PMONCTN not implemented\n"); 1432292SN/A default: 1449915Ssteve.reinhardt@amd.com panic("Default in PChip Read reached reading 0x%x\n", daddr); 1451060SN/A } 1469915Ssteve.reinhardt@amd.com pkt->makeAtomicResponse(); 1479915Ssteve.reinhardt@amd.com return pioDelay; 1481060SN/A 1499915Ssteve.reinhardt@amd.com} 1501060SN/A 1512455SN/ATick 1529915Ssteve.reinhardt@amd.comTsunamiPChip::write(PacketPtr pkt) 1532455SN/A{ 1549915Ssteve.reinhardt@amd.com assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 1551060SN/A Addr daddr = (pkt->getAddr() - pioAddr) >> 6; 1561060SN/A 1579915Ssteve.reinhardt@amd.com assert(pkt->getSize() == sizeof(uint64_t)); 1582455SN/A 1599915Ssteve.reinhardt@amd.com DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize()); 1609915Ssteve.reinhardt@amd.com 1612455SN/A switch(daddr) { 1629915Ssteve.reinhardt@amd.com case TSDEV_PC_WSBA0: 1632455SN/A wsba[0] = pkt->get<uint64_t>(); 1649915Ssteve.reinhardt@amd.com break; 1652455SN/A case TSDEV_PC_WSBA1: 1662455SN/A wsba[1] = pkt->get<uint64_t>(); 1672690Sktlim@umich.edu break; 1682455SN/A case TSDEV_PC_WSBA2: 1692455SN/A wsba[2] = pkt->get<uint64_t>(); 1701060SN/A break; 1711060SN/A case TSDEV_PC_WSBA3: 1722292SN/A wsba[3] = pkt->get<uint64_t>(); 1731060SN/A break; 1741060SN/A case TSDEV_PC_WSM0: 1759915Ssteve.reinhardt@amd.com wsm[0] = pkt->get<uint64_t>(); 1761061SN/A break; 1772690Sktlim@umich.edu case TSDEV_PC_WSM1: 1781060SN/A wsm[1] = pkt->get<uint64_t>(); 1791060SN/A break; 1802292SN/A case TSDEV_PC_WSM2: 1812292SN/A wsm[2] = pkt->get<uint64_t>(); 1821060SN/A break; 1831060SN/A case TSDEV_PC_WSM3: 1842292SN/A wsm[3] = pkt->get<uint64_t>(); 1852455SN/A break; 1861060SN/A case TSDEV_PC_TBA0: 1879915Ssteve.reinhardt@amd.com tba[0] = pkt->get<uint64_t>(); 1889915Ssteve.reinhardt@amd.com break; 1891060SN/A case TSDEV_PC_TBA1: 1909915Ssteve.reinhardt@amd.com tba[1] = pkt->get<uint64_t>(); 1911061SN/A break; 1922690Sktlim@umich.edu case TSDEV_PC_TBA2: 1932690Sktlim@umich.edu tba[2] = pkt->get<uint64_t>(); 1941060SN/A break; 1954642Sgblack@eecs.umich.edu case TSDEV_PC_TBA3: 1969915Ssteve.reinhardt@amd.com tba[3] = pkt->get<uint64_t>(); 1974642Sgblack@eecs.umich.edu break; 1989915Ssteve.reinhardt@amd.com case TSDEV_PC_PCTL: 1991060SN/A pctl = pkt->get<uint64_t>(); 2001060SN/A break; 2012455SN/A case TSDEV_PC_PLAT: 2022455SN/A panic("PC_PLAT not implemented\n"); 2039915Ssteve.reinhardt@amd.com case TSDEV_PC_RES: 2049915Ssteve.reinhardt@amd.com panic("PC_RES not implemented\n"); 2052455SN/A case TSDEV_PC_PERROR: 2069915Ssteve.reinhardt@amd.com break; 2072455SN/A case TSDEV_PC_PERRMASK: 2082690Sktlim@umich.edu panic("PC_PERRMASK not implemented\n"); 2092455SN/A case TSDEV_PC_PERRSET: 2102455SN/A panic("PC_PERRSET not implemented\n"); 2119915Ssteve.reinhardt@amd.com case TSDEV_PC_TLBIV: 2121060SN/A panic("PC_TLBIV not implemented\n"); 2131060SN/A case TSDEV_PC_TLBIA: 2141060SN/A break; // value ignored, supposted to invalidate SG TLB 2151060SN/A case TSDEV_PC_PMONCTL: 2169915Ssteve.reinhardt@amd.com panic("PC_PMONCTL not implemented\n"); 2179915Ssteve.reinhardt@amd.com case TSDEV_PC_PMONCNT: 218 panic("PC_PMONCTN not implemented\n"); 219 default: 220 panic("Default in PChip write reached reading 0x%x\n", daddr); 221 222 } // uint64_t 223 224 pkt->makeAtomicResponse(); 225 return pioDelay; 226} 227 228#define DMA_ADDR_MASK ULL(0x3ffffffff) 229 230Addr 231TsunamiPChip::translatePciToDma(Addr busAddr) 232{ 233 // compare the address to the window base registers 234 uint64_t tbaMask = 0; 235 uint64_t baMask = 0; 236 237 uint64_t windowMask = 0; 238 uint64_t windowBase = 0; 239 240 uint64_t pteEntry = 0; 241 242 Addr pteAddr; 243 Addr dmaAddr; 244 245#if 0 246 DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); 247 for (int i = 0; i < 4; i++) { 248 DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", 249 i, wsba[i], wsm[i]); 250 251 windowBase = wsba[i]; 252 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 253 254 if ((busAddr & windowMask) == (windowBase & windowMask)) { 255 DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", 256 i, windowBase, windowMask, (busAddr & windowMask), 257 (windowBase & windowMask)); 258 } 259 } 260#endif 261 262 for (int i = 0; i < 4; i++) { 263 264 windowBase = wsba[i]; 265 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 266 267 if ((busAddr & windowMask) == (windowBase & windowMask)) { 268 269 if (wsba[i] & 0x1) { // see if enabled 270 if (wsba[i] & 0x2) { // see if SG bit is set 271 /** @todo 272 This currently is faked by just doing a direct 273 read from memory, however, to be realistic, this 274 needs to actually do a bus transaction. The process 275 is explained in the tsunami documentation on page 276 10-12 and basically munges the address to look up a 277 PTE from a table in memory and then uses that mapping 278 to create an address for the SG page 279 */ 280 281 tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); 282 baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); 283 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 284 285 sys->physProxy.readBlob(pteAddr, (uint8_t*)&pteEntry, 286 sizeof(uint64_t)); 287 288 dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); 289 290 } else { 291 baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); 292 tbaMask = ~baMask; 293 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 294 } 295 296 return (dmaAddr & DMA_ADDR_MASK); 297 } 298 } 299 } 300 301 // if no match was found, then return the original address 302 return busAddr; 303} 304 305Addr 306TsunamiPChip::calcConfigAddr(int bus, int dev, int func) 307{ 308 assert(func < 8); 309 assert(dev < 32); 310 assert(bus == 0); 311 312 return TsunamiPciBus0Config | (func << 8) | (dev << 11); 313} 314 315Addr 316TsunamiPChip::calcIOAddr(Addr addr) 317{ 318 return TSUNAMI_PCI0_IO + addr; 319} 320 321Addr 322TsunamiPChip::calcMemAddr(Addr addr) 323{ 324 return TSUNAMI_PCI0_MEMORY + addr; 325} 326 327void 328TsunamiPChip::serialize(std::ostream &os) 329{ 330 SERIALIZE_SCALAR(pctl); 331 SERIALIZE_ARRAY(wsba, 4); 332 SERIALIZE_ARRAY(wsm, 4); 333 SERIALIZE_ARRAY(tba, 4); 334} 335 336void 337TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 338{ 339 UNSERIALIZE_SCALAR(pctl); 340 UNSERIALIZE_ARRAY(wsba, 4); 341 UNSERIALIZE_ARRAY(wsm, 4); 342 UNSERIALIZE_ARRAY(tba, 4); 343} 344 345 346TsunamiPChip * 347TsunamiPChipParams::create() 348{ 349 return new TsunamiPChip(this); 350} 351