tsunami_pchip.cc revision 4762
114039Sstacze01@arm.com/* 214039Sstacze01@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 314039Sstacze01@arm.com * All rights reserved. 414039Sstacze01@arm.com * 514039Sstacze01@arm.com * Redistribution and use in source and binary forms, with or without 614039Sstacze01@arm.com * modification, are permitted provided that the following conditions are 714039Sstacze01@arm.com * met: redistributions of source code must retain the above copyright 814039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer; 914039Sstacze01@arm.com * redistributions in binary form must reproduce the above copyright 1014039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer in the 1114039Sstacze01@arm.com * documentation and/or other materials provided with the distribution; 1214039Sstacze01@arm.com * neither the name of the copyright holders nor the names of its 1314039Sstacze01@arm.com * contributors may be used to endorse or promote products derived from 1414039Sstacze01@arm.com * this software without specific prior written permission. 1514039Sstacze01@arm.com * 1614039Sstacze01@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1714039Sstacze01@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1814039Sstacze01@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1914039Sstacze01@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2014039Sstacze01@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2114039Sstacze01@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2214039Sstacze01@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2314039Sstacze01@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2414039Sstacze01@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2514039Sstacze01@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2614039Sstacze01@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2714039Sstacze01@arm.com * 2814039Sstacze01@arm.com * Authors: Ali Saidi 2914039Sstacze01@arm.com * Andrew Schultz 3014039Sstacze01@arm.com */ 3114039Sstacze01@arm.com 3214039Sstacze01@arm.com/** @file 3314039Sstacze01@arm.com * Tsunami PChip (pci) 3414039Sstacze01@arm.com */ 3514039Sstacze01@arm.com 3614039Sstacze01@arm.com#include <deque> 3714039Sstacze01@arm.com#include <string> 3814039Sstacze01@arm.com#include <vector> 3914039Sstacze01@arm.com 4014039Sstacze01@arm.com#include "base/trace.hh" 4114039Sstacze01@arm.com#include "dev/alpha/tsunami_pchip.hh" 4214039Sstacze01@arm.com#include "dev/alpha/tsunamireg.h" 4314039Sstacze01@arm.com#include "dev/alpha/tsunami.hh" 4414039Sstacze01@arm.com#include "mem/packet.hh" 4514039Sstacze01@arm.com#include "mem/packet_access.hh" 4614039Sstacze01@arm.com#include "sim/system.hh" 4714039Sstacze01@arm.com 4814039Sstacze01@arm.comusing namespace std; 4914039Sstacze01@arm.com//Should this be AlphaISA? 5014039Sstacze01@arm.comusing namespace TheISA; 5114252Sgabeblack@google.com 5214039Sstacze01@arm.comTsunamiPChip::TsunamiPChip(const Params *p) 5314039Sstacze01@arm.com: BasicPioDevice(p) 5414039Sstacze01@arm.com{ 5514039Sstacze01@arm.com pioSize = 0x1000; 5614039Sstacze01@arm.com 5714252Sgabeblack@google.com for (int i = 0; i < 4; i++) { 5814039Sstacze01@arm.com wsba[i] = 0; 5914064Sadrian.herrera@arm.com wsm[i] = 0; 6014064Sadrian.herrera@arm.com tba[i] = 0; 6114064Sadrian.herrera@arm.com } 6214039Sstacze01@arm.com 6314039Sstacze01@arm.com // initialize pchip control register 6414039Sstacze01@arm.com pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); 6514039Sstacze01@arm.com 6614039Sstacze01@arm.com //Set back pointer in tsunami 6714039Sstacze01@arm.com p->tsunami->pchip = this; 6814039Sstacze01@arm.com} 6914039Sstacze01@arm.com 7014039Sstacze01@arm.comTick 7114039Sstacze01@arm.comTsunamiPChip::read(PacketPtr pkt) 7214039Sstacze01@arm.com{ 7314039Sstacze01@arm.com assert(pkt->result == Packet::Unknown); 7414039Sstacze01@arm.com assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 7514039Sstacze01@arm.com 7614039Sstacze01@arm.com pkt->allocate(); 7714039Sstacze01@arm.com Addr daddr = (pkt->getAddr() - pioAddr) >> 6;; 7814039Sstacze01@arm.com assert(pkt->getSize() == sizeof(uint64_t)); 7914039Sstacze01@arm.com 8014039Sstacze01@arm.com 8114039Sstacze01@arm.com DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize()); 8214039Sstacze01@arm.com 8314039Sstacze01@arm.com switch(daddr) { 8414039Sstacze01@arm.com case TSDEV_PC_WSBA0: 8514039Sstacze01@arm.com pkt->set(wsba[0]); 8614223Sgiacomo.travaglini@arm.com break; 8714039Sstacze01@arm.com case TSDEV_PC_WSBA1: 8814039Sstacze01@arm.com pkt->set(wsba[1]); 8914039Sstacze01@arm.com break; 9014039Sstacze01@arm.com case TSDEV_PC_WSBA2: 9114039Sstacze01@arm.com pkt->set(wsba[2]); 9214039Sstacze01@arm.com break; 9314039Sstacze01@arm.com case TSDEV_PC_WSBA3: 9414039Sstacze01@arm.com pkt->set(wsba[3]); 9514039Sstacze01@arm.com break; 9614039Sstacze01@arm.com case TSDEV_PC_WSM0: 9714039Sstacze01@arm.com pkt->set(wsm[0]); 9814039Sstacze01@arm.com break; 9914039Sstacze01@arm.com case TSDEV_PC_WSM1: 10014039Sstacze01@arm.com pkt->set(wsm[1]); 10114039Sstacze01@arm.com break; 10214039Sstacze01@arm.com case TSDEV_PC_WSM2: 10314039Sstacze01@arm.com pkt->set(wsm[2]); 10414039Sstacze01@arm.com break; 10514039Sstacze01@arm.com case TSDEV_PC_WSM3: 10614039Sstacze01@arm.com pkt->set(wsm[3]); 10714039Sstacze01@arm.com break; 10814039Sstacze01@arm.com case TSDEV_PC_TBA0: 10914039Sstacze01@arm.com pkt->set(tba[0]); 11014039Sstacze01@arm.com break; 11114039Sstacze01@arm.com case TSDEV_PC_TBA1: 11214039Sstacze01@arm.com pkt->set(tba[1]); 11314039Sstacze01@arm.com break; 11414039Sstacze01@arm.com case TSDEV_PC_TBA2: 11514039Sstacze01@arm.com pkt->set(tba[2]); 11614039Sstacze01@arm.com break; 11714039Sstacze01@arm.com case TSDEV_PC_TBA3: 11814039Sstacze01@arm.com pkt->set(tba[3]); 11914039Sstacze01@arm.com break; 12014092Smatteo.andreozzi@arm.com case TSDEV_PC_PCTL: 12114039Sstacze01@arm.com pkt->set(pctl); 12214039Sstacze01@arm.com break; 12314039Sstacze01@arm.com case TSDEV_PC_PLAT: 12414039Sstacze01@arm.com panic("PC_PLAT not implemented\n"); 12514039Sstacze01@arm.com case TSDEV_PC_RES: 12614039Sstacze01@arm.com panic("PC_RES not implemented\n"); 12714039Sstacze01@arm.com case TSDEV_PC_PERROR: 12814039Sstacze01@arm.com pkt->set((uint64_t)0x00); 12914039Sstacze01@arm.com break; 13014039Sstacze01@arm.com case TSDEV_PC_PERRMASK: 13114064Sadrian.herrera@arm.com pkt->set((uint64_t)0x00); 13214064Sadrian.herrera@arm.com break; 13314064Sadrian.herrera@arm.com case TSDEV_PC_PERRSET: 13414064Sadrian.herrera@arm.com panic("PC_PERRSET not implemented\n"); 13514064Sadrian.herrera@arm.com case TSDEV_PC_TLBIV: 13614064Sadrian.herrera@arm.com panic("PC_TLBIV not implemented\n"); 13714064Sadrian.herrera@arm.com case TSDEV_PC_TLBIA: 13814064Sadrian.herrera@arm.com pkt->set((uint64_t)0x00); // shouldn't be readable, but linux 13914039Sstacze01@arm.com break; 14014039Sstacze01@arm.com case TSDEV_PC_PMONCTL: 14114039Sstacze01@arm.com panic("PC_PMONCTL not implemented\n"); 14214039Sstacze01@arm.com case TSDEV_PC_PMONCNT: 14314039Sstacze01@arm.com panic("PC_PMONCTN not implemented\n"); 144 default: 145 panic("Default in PChip Read reached reading 0x%x\n", daddr); 146 } 147 pkt->result = Packet::Success; 148 return pioDelay; 149 150} 151 152Tick 153TsunamiPChip::write(PacketPtr pkt) 154{ 155 assert(pkt->result == Packet::Unknown); 156 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 157 Addr daddr = (pkt->getAddr() - pioAddr) >> 6; 158 159 assert(pkt->getSize() == sizeof(uint64_t)); 160 161 DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize()); 162 163 switch(daddr) { 164 case TSDEV_PC_WSBA0: 165 wsba[0] = pkt->get<uint64_t>(); 166 break; 167 case TSDEV_PC_WSBA1: 168 wsba[1] = pkt->get<uint64_t>(); 169 break; 170 case TSDEV_PC_WSBA2: 171 wsba[2] = pkt->get<uint64_t>(); 172 break; 173 case TSDEV_PC_WSBA3: 174 wsba[3] = pkt->get<uint64_t>(); 175 break; 176 case TSDEV_PC_WSM0: 177 wsm[0] = pkt->get<uint64_t>(); 178 break; 179 case TSDEV_PC_WSM1: 180 wsm[1] = pkt->get<uint64_t>(); 181 break; 182 case TSDEV_PC_WSM2: 183 wsm[2] = pkt->get<uint64_t>(); 184 break; 185 case TSDEV_PC_WSM3: 186 wsm[3] = pkt->get<uint64_t>(); 187 break; 188 case TSDEV_PC_TBA0: 189 tba[0] = pkt->get<uint64_t>(); 190 break; 191 case TSDEV_PC_TBA1: 192 tba[1] = pkt->get<uint64_t>(); 193 break; 194 case TSDEV_PC_TBA2: 195 tba[2] = pkt->get<uint64_t>(); 196 break; 197 case TSDEV_PC_TBA3: 198 tba[3] = pkt->get<uint64_t>(); 199 break; 200 case TSDEV_PC_PCTL: 201 pctl = pkt->get<uint64_t>(); 202 break; 203 case TSDEV_PC_PLAT: 204 panic("PC_PLAT not implemented\n"); 205 case TSDEV_PC_RES: 206 panic("PC_RES not implemented\n"); 207 case TSDEV_PC_PERROR: 208 break; 209 case TSDEV_PC_PERRMASK: 210 panic("PC_PERRMASK not implemented\n"); 211 case TSDEV_PC_PERRSET: 212 panic("PC_PERRSET not implemented\n"); 213 case TSDEV_PC_TLBIV: 214 panic("PC_TLBIV not implemented\n"); 215 case TSDEV_PC_TLBIA: 216 break; // value ignored, supposted to invalidate SG TLB 217 case TSDEV_PC_PMONCTL: 218 panic("PC_PMONCTL not implemented\n"); 219 case TSDEV_PC_PMONCNT: 220 panic("PC_PMONCTN not implemented\n"); 221 default: 222 panic("Default in PChip write reached reading 0x%x\n", daddr); 223 224 } // uint64_t 225 226 pkt->result = Packet::Success; 227 return pioDelay; 228} 229 230#define DMA_ADDR_MASK ULL(0x3ffffffff) 231 232Addr 233TsunamiPChip::translatePciToDma(Addr busAddr) 234{ 235 // compare the address to the window base registers 236 uint64_t tbaMask = 0; 237 uint64_t baMask = 0; 238 239 uint64_t windowMask = 0; 240 uint64_t windowBase = 0; 241 242 uint64_t pteEntry = 0; 243 244 Addr pteAddr; 245 Addr dmaAddr; 246 247#if 0 248 DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); 249 for (int i = 0; i < 4; i++) { 250 DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", 251 i, wsba[i], wsm[i]); 252 253 windowBase = wsba[i]; 254 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 255 256 if ((busAddr & windowMask) == (windowBase & windowMask)) { 257 DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", 258 i, windowBase, windowMask, (busAddr & windowMask), 259 (windowBase & windowMask)); 260 } 261 } 262#endif 263 264 for (int i = 0; i < 4; i++) { 265 266 windowBase = wsba[i]; 267 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 268 269 if ((busAddr & windowMask) == (windowBase & windowMask)) { 270 271 if (wsba[i] & 0x1) { // see if enabled 272 if (wsba[i] & 0x2) { // see if SG bit is set 273 /** @todo 274 This currently is faked by just doing a direct 275 read from memory, however, to be realistic, this 276 needs to actually do a bus transaction. The process 277 is explained in the tsunami documentation on page 278 10-12 and basically munges the address to look up a 279 PTE from a table in memory and then uses that mapping 280 to create an address for the SG page 281 */ 282 283 tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); 284 baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); 285 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 286 287 pioPort->readBlob(pteAddr, (uint8_t*)&pteEntry, sizeof(uint64_t)); 288 289 dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); 290 291 } else { 292 baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); 293 tbaMask = ~baMask; 294 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 295 } 296 297 return (dmaAddr & DMA_ADDR_MASK); 298 } 299 } 300 } 301 302 // if no match was found, then return the original address 303 return busAddr; 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 315 316 317void 318TsunamiPChip::serialize(std::ostream &os) 319{ 320 SERIALIZE_SCALAR(pctl); 321 SERIALIZE_ARRAY(wsba, 4); 322 SERIALIZE_ARRAY(wsm, 4); 323 SERIALIZE_ARRAY(tba, 4); 324} 325 326void 327TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 328{ 329 UNSERIALIZE_SCALAR(pctl); 330 UNSERIALIZE_ARRAY(wsba, 4); 331 UNSERIALIZE_ARRAY(wsm, 4); 332 UNSERIALIZE_ARRAY(tba, 4); 333} 334 335 336TsunamiPChip * 337TsunamiPChipParams::create() 338{ 339 return new TsunamiPChip(this); 340} 341