tsunami_pchip.cc revision 909
14484Sbinkertn@umich.edu/* 24484Sbinkertn@umich.edu * Copyright (c) 2004 The Regents of The University of Michigan 34484Sbinkertn@umich.edu * All rights reserved. 44484Sbinkertn@umich.edu * 54484Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without 64484Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are 74484Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright 84484Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer; 94484Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright 104484Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the 114484Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution; 124484Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its 134484Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from 144484Sbinkertn@umich.edu * this software without specific prior written permission. 154484Sbinkertn@umich.edu * 164484Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174484Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184484Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194484Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204484Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214484Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224484Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234484Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244484Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254484Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264484Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274484Sbinkertn@umich.edu */ 284484Sbinkertn@umich.edu 294484Sbinkertn@umich.edu/* @file 304484Sbinkertn@umich.edu * Tsunami PChip (pci) 314494Ssaidi@eecs.umich.edu */ 324484Sbinkertn@umich.edu 334484Sbinkertn@umich.edu#include <deque> 344484Sbinkertn@umich.edu#include <string> 354484Sbinkertn@umich.edu#include <vector> 364484Sbinkertn@umich.edu 374484Sbinkertn@umich.edu#include "base/trace.hh" 384484Sbinkertn@umich.edu#include "dev/tsunami_pchip.hh" 394484Sbinkertn@umich.edu#include "dev/tsunamireg.h" 404484Sbinkertn@umich.edu#include "dev/tsunami.hh" 414484Sbinkertn@umich.edu#include "mem/bus/bus.hh" 424484Sbinkertn@umich.edu#include "mem/bus/pio_interface.hh" 434484Sbinkertn@umich.edu#include "mem/bus/pio_interface_impl.hh" 444484Sbinkertn@umich.edu#include "mem/functional_mem/memory_control.hh" 454484Sbinkertn@umich.edu#include "mem/functional_mem/physical_memory.hh" 464484Sbinkertn@umich.edu#include "sim/builder.hh" 474484Sbinkertn@umich.edu#include "sim/system.hh" 484484Sbinkertn@umich.edu 494484Sbinkertn@umich.eduusing namespace std; 504484Sbinkertn@umich.edu 514484Sbinkertn@umich.eduTsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, 524484Sbinkertn@umich.edu MemoryController *mmu, HierParams *hier, 534484Sbinkertn@umich.edu Bus *bus) 544484Sbinkertn@umich.edu : PioDevice(name), addr(a), tsunami(t) 554484Sbinkertn@umich.edu{ 564484Sbinkertn@umich.edu mmu->add_child(this, Range<Addr>(addr, addr + size)); 574484Sbinkertn@umich.edu 584484Sbinkertn@umich.edu for (int i = 0; i < 4; i++) { 594484Sbinkertn@umich.edu wsba[i] = 0; 604484Sbinkertn@umich.edu wsm[i] = 0; 614484Sbinkertn@umich.edu tba[i] = 0; 624484Sbinkertn@umich.edu } 634484Sbinkertn@umich.edu 644484Sbinkertn@umich.edu if (bus) { 654484Sbinkertn@umich.edu pioInterface = newPioInterface(name, hier, bus, this, 664484Sbinkertn@umich.edu &TsunamiPChip::cacheAccess); 674484Sbinkertn@umich.edu pioInterface->addAddrRange(addr, addr + size - 1); 684484Sbinkertn@umich.edu } 694484Sbinkertn@umich.edu 704484Sbinkertn@umich.edu 714484Sbinkertn@umich.edu // initialize pchip control register 724484Sbinkertn@umich.edu pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); 734484Sbinkertn@umich.edu 744484Sbinkertn@umich.edu //Set back pointer in tsunami 754484Sbinkertn@umich.edu tsunami->pchip = this; 764484Sbinkertn@umich.edu} 774484Sbinkertn@umich.edu 784484Sbinkertn@umich.eduFault 794484Sbinkertn@umich.eduTsunamiPChip::read(MemReqPtr &req, uint8_t *data) 804484Sbinkertn@umich.edu{ 814484Sbinkertn@umich.edu DPRINTF(Tsunami, "read va=%#x size=%d\n", 824484Sbinkertn@umich.edu req->vaddr, req->size); 834484Sbinkertn@umich.edu 844484Sbinkertn@umich.edu Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 854484Sbinkertn@umich.edu 864484Sbinkertn@umich.edu switch (req->size) { 874484Sbinkertn@umich.edu 884484Sbinkertn@umich.edu case sizeof(uint64_t): 894484Sbinkertn@umich.edu switch(daddr) { 904484Sbinkertn@umich.edu case TSDEV_PC_WSBA0: 914484Sbinkertn@umich.edu *(uint64_t*)data = wsba[0]; 924484Sbinkertn@umich.edu return No_Fault; 934484Sbinkertn@umich.edu case TSDEV_PC_WSBA1: 944484Sbinkertn@umich.edu *(uint64_t*)data = wsba[1]; 954484Sbinkertn@umich.edu return No_Fault; 964484Sbinkertn@umich.edu case TSDEV_PC_WSBA2: 974484Sbinkertn@umich.edu *(uint64_t*)data = wsba[2]; 984484Sbinkertn@umich.edu return No_Fault; 994484Sbinkertn@umich.edu case TSDEV_PC_WSBA3: 1004484Sbinkertn@umich.edu *(uint64_t*)data = wsba[3]; 1014484Sbinkertn@umich.edu return No_Fault; 1024484Sbinkertn@umich.edu case TSDEV_PC_WSM0: 1034484Sbinkertn@umich.edu *(uint64_t*)data = wsm[0]; 1044484Sbinkertn@umich.edu return No_Fault; 1054484Sbinkertn@umich.edu case TSDEV_PC_WSM1: 1064484Sbinkertn@umich.edu *(uint64_t*)data = wsm[1]; 1074484Sbinkertn@umich.edu return No_Fault; 1084484Sbinkertn@umich.edu case TSDEV_PC_WSM2: 1094484Sbinkertn@umich.edu *(uint64_t*)data = wsm[2]; 1104484Sbinkertn@umich.edu return No_Fault; 1114484Sbinkertn@umich.edu case TSDEV_PC_WSM3: 1124484Sbinkertn@umich.edu *(uint64_t*)data = wsm[3]; 1134484Sbinkertn@umich.edu return No_Fault; 1144484Sbinkertn@umich.edu case TSDEV_PC_TBA0: 1154484Sbinkertn@umich.edu *(uint64_t*)data = tba[0]; 1164484Sbinkertn@umich.edu return No_Fault; 1174484Sbinkertn@umich.edu case TSDEV_PC_TBA1: 1184484Sbinkertn@umich.edu *(uint64_t*)data = tba[1]; 1194484Sbinkertn@umich.edu return No_Fault; 1204484Sbinkertn@umich.edu case TSDEV_PC_TBA2: 1214484Sbinkertn@umich.edu *(uint64_t*)data = tba[2]; 1224484Sbinkertn@umich.edu return No_Fault; 1234484Sbinkertn@umich.edu case TSDEV_PC_TBA3: 1244484Sbinkertn@umich.edu *(uint64_t*)data = tba[3]; 1254484Sbinkertn@umich.edu return No_Fault; 1264484Sbinkertn@umich.edu case TSDEV_PC_PCTL: 1274484Sbinkertn@umich.edu *(uint64_t*)data = pctl; 1284484Sbinkertn@umich.edu return No_Fault; 1294484Sbinkertn@umich.edu case TSDEV_PC_PLAT: 1304484Sbinkertn@umich.edu panic("PC_PLAT not implemented\n"); 1314484Sbinkertn@umich.edu case TSDEV_PC_RES: 1324484Sbinkertn@umich.edu panic("PC_RES not implemented\n"); 1334484Sbinkertn@umich.edu case TSDEV_PC_PERROR: 1344484Sbinkertn@umich.edu *(uint64_t*)data = 0x00; 1354484Sbinkertn@umich.edu return No_Fault; 1364484Sbinkertn@umich.edu case TSDEV_PC_PERRMASK: 1374484Sbinkertn@umich.edu *(uint64_t*)data = 0x00; 1384484Sbinkertn@umich.edu return No_Fault; 1394484Sbinkertn@umich.edu case TSDEV_PC_PERRSET: 1404484Sbinkertn@umich.edu panic("PC_PERRSET not implemented\n"); 1414484Sbinkertn@umich.edu case TSDEV_PC_TLBIV: 1424484Sbinkertn@umich.edu panic("PC_TLBIV not implemented\n"); 1434484Sbinkertn@umich.edu case TSDEV_PC_TLBIA: 1444484Sbinkertn@umich.edu *(uint64_t*)data = 0x00; // shouldn't be readable, but linux 1454484Sbinkertn@umich.edu return No_Fault; 1464484Sbinkertn@umich.edu case TSDEV_PC_PMONCTL: 1474484Sbinkertn@umich.edu panic("PC_PMONCTL not implemented\n"); 1484484Sbinkertn@umich.edu case TSDEV_PC_PMONCNT: 1494484Sbinkertn@umich.edu panic("PC_PMONCTN not implemented\n"); 1504484Sbinkertn@umich.edu default: 1514484Sbinkertn@umich.edu panic("Default in PChip Read reached reading 0x%x\n", daddr); 1524484Sbinkertn@umich.edu 1534484Sbinkertn@umich.edu } // uint64_t 1544484Sbinkertn@umich.edu 1554484Sbinkertn@umich.edu break; 1564484Sbinkertn@umich.edu case sizeof(uint32_t): 1574484Sbinkertn@umich.edu case sizeof(uint16_t): 1584484Sbinkertn@umich.edu case sizeof(uint8_t): 1594484Sbinkertn@umich.edu default: 1604484Sbinkertn@umich.edu panic("invalid access size(?) for tsunami register!\n\n"); 1614484Sbinkertn@umich.edu } 1624484Sbinkertn@umich.edu DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); 1634484Sbinkertn@umich.edu 1644484Sbinkertn@umich.edu return No_Fault; 1654484Sbinkertn@umich.edu} 1664484Sbinkertn@umich.edu 1674484Sbinkertn@umich.eduFault 1684484Sbinkertn@umich.eduTsunamiPChip::write(MemReqPtr &req, const uint8_t *data) 1694484Sbinkertn@umich.edu{ 1704484Sbinkertn@umich.edu DPRINTF(Tsunami, "write - va=%#x size=%d \n", 1714484Sbinkertn@umich.edu req->vaddr, req->size); 1724484Sbinkertn@umich.edu 1734484Sbinkertn@umich.edu Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 1744484Sbinkertn@umich.edu 1754484Sbinkertn@umich.edu switch (req->size) { 1764484Sbinkertn@umich.edu 1774484Sbinkertn@umich.edu case sizeof(uint64_t): 1784484Sbinkertn@umich.edu switch(daddr) { 1794484Sbinkertn@umich.edu case TSDEV_PC_WSBA0: 1804484Sbinkertn@umich.edu wsba[0] = *(uint64_t*)data; 1814484Sbinkertn@umich.edu return No_Fault; 1824484Sbinkertn@umich.edu case TSDEV_PC_WSBA1: 1834484Sbinkertn@umich.edu wsba[1] = *(uint64_t*)data; 1844484Sbinkertn@umich.edu return No_Fault; 1854484Sbinkertn@umich.edu case TSDEV_PC_WSBA2: 1864484Sbinkertn@umich.edu wsba[2] = *(uint64_t*)data; 1874484Sbinkertn@umich.edu return No_Fault; 1884484Sbinkertn@umich.edu case TSDEV_PC_WSBA3: 1894484Sbinkertn@umich.edu wsba[3] = *(uint64_t*)data; 1904484Sbinkertn@umich.edu return No_Fault; 1914484Sbinkertn@umich.edu case TSDEV_PC_WSM0: 1924484Sbinkertn@umich.edu wsm[0] = *(uint64_t*)data; 1934484Sbinkertn@umich.edu return No_Fault; 1944484Sbinkertn@umich.edu case TSDEV_PC_WSM1: 1954484Sbinkertn@umich.edu wsm[1] = *(uint64_t*)data; 1964484Sbinkertn@umich.edu return No_Fault; 1974484Sbinkertn@umich.edu case TSDEV_PC_WSM2: 1984484Sbinkertn@umich.edu wsm[2] = *(uint64_t*)data; 1994484Sbinkertn@umich.edu return No_Fault; 2004484Sbinkertn@umich.edu case TSDEV_PC_WSM3: 2014484Sbinkertn@umich.edu wsm[3] = *(uint64_t*)data; 2024484Sbinkertn@umich.edu return No_Fault; 2034484Sbinkertn@umich.edu case TSDEV_PC_TBA0: 2044484Sbinkertn@umich.edu tba[0] = *(uint64_t*)data; 2054484Sbinkertn@umich.edu return No_Fault; 2064484Sbinkertn@umich.edu case TSDEV_PC_TBA1: 207 tba[1] = *(uint64_t*)data; 208 return No_Fault; 209 case TSDEV_PC_TBA2: 210 tba[2] = *(uint64_t*)data; 211 return No_Fault; 212 case TSDEV_PC_TBA3: 213 tba[3] = *(uint64_t*)data; 214 return No_Fault; 215 case TSDEV_PC_PCTL: 216 pctl = *(uint64_t*)data; 217 return No_Fault; 218 case TSDEV_PC_PLAT: 219 panic("PC_PLAT not implemented\n"); 220 case TSDEV_PC_RES: 221 panic("PC_RES not implemented\n"); 222 case TSDEV_PC_PERROR: 223 return No_Fault; 224 case TSDEV_PC_PERRMASK: 225 panic("PC_PERRMASK not implemented\n"); 226 case TSDEV_PC_PERRSET: 227 panic("PC_PERRSET not implemented\n"); 228 case TSDEV_PC_TLBIV: 229 panic("PC_TLBIV not implemented\n"); 230 case TSDEV_PC_TLBIA: 231 return No_Fault; // value ignored, supposted to invalidate SG TLB 232 case TSDEV_PC_PMONCTL: 233 panic("PC_PMONCTL not implemented\n"); 234 case TSDEV_PC_PMONCNT: 235 panic("PC_PMONCTN not implemented\n"); 236 default: 237 panic("Default in PChip Read reached reading 0x%x\n", daddr); 238 239 } // uint64_t 240 241 break; 242 case sizeof(uint32_t): 243 case sizeof(uint16_t): 244 case sizeof(uint8_t): 245 default: 246 panic("invalid access size(?) for tsunami register!\n\n"); 247 } 248 249 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); 250 251 return No_Fault; 252} 253 254#define DMA_ADDR_MASK ULL(0x3ffffffff) 255 256Addr 257TsunamiPChip::translatePciToDma(Addr busAddr) 258{ 259 // compare the address to the window base registers 260 uint64_t tbaMask = 0; 261 uint64_t baMask = 0; 262 263 uint64_t windowMask = 0; 264 uint64_t windowBase = 0; 265 266 uint64_t pteEntry = 0; 267 268 Addr pteAddr; 269 Addr dmaAddr; 270 271#if 0 272 DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); 273 for (int i = 0; i < 4; i++) { 274 DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", 275 i, wsba[i], wsm[i]); 276 277 windowBase = wsba[i]; 278 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 279 280 if ((busAddr & windowMask) == (windowBase & windowMask)) { 281 DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", 282 i, windowBase, windowMask, (busAddr & windowMask), 283 (windowBase & windowMask)); 284 } 285 } 286#endif 287 288 for (int i = 0; i < 4; i++) { 289 290 windowBase = wsba[i]; 291 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 292 293 if ((busAddr & windowMask) == (windowBase & windowMask)) { 294 295 if (wsba[i] & 0x1) { // see if enabled 296 if (wsba[i] & 0x2) { // see if SG bit is set 297 /** @todo 298 This currently is faked by just doing a direct 299 read from memory, however, to be realistic, this 300 needs to actually do a bus transaction. The process 301 is explained in the tsunami documentation on page 302 10-12 and basically munges the address to look up a 303 PTE from a table in memory and then uses that mapping 304 to create an address for the SG page 305 */ 306 307 tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); 308 baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); 309 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 310 311 memcpy((void *)&pteEntry, 312 tsunami->system-> 313 physmem->dma_addr(pteAddr, sizeof(uint64_t)), 314 sizeof(uint64_t)); 315 316 dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); 317 318 } else { 319 baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); 320 tbaMask = ~baMask; 321 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 322 } 323 324 return (dmaAddr & DMA_ADDR_MASK); 325 } 326 } 327 } 328 329 // if no match was found, then return the original address 330 return busAddr; 331} 332 333void 334TsunamiPChip::serialize(std::ostream &os) 335{ 336 SERIALIZE_SCALAR(pctl); 337 SERIALIZE_ARRAY(wsba, 4); 338 SERIALIZE_ARRAY(wsm, 4); 339 SERIALIZE_ARRAY(tba, 4); 340} 341 342void 343TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 344{ 345 UNSERIALIZE_SCALAR(pctl); 346 UNSERIALIZE_ARRAY(wsba, 4); 347 UNSERIALIZE_ARRAY(wsm, 4); 348 UNSERIALIZE_ARRAY(tba, 4); 349} 350 351Tick 352TsunamiPChip::cacheAccess(MemReqPtr &req) 353{ 354 return curTick + 1000; 355} 356 357BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 358 359 SimObjectParam<Tsunami *> tsunami; 360 SimObjectParam<MemoryController *> mmu; 361 Param<Addr> addr; 362 SimObjectParam<Bus*> io_bus; 363 SimObjectParam<HierParams *> hier; 364 365END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 366 367BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 368 369 INIT_PARAM(tsunami, "Tsunami"), 370 INIT_PARAM(mmu, "Memory Controller"), 371 INIT_PARAM(addr, "Device Address"), 372 INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL), 373 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) 374 375END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 376 377CREATE_SIM_OBJECT(TsunamiPChip) 378{ 379 return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu, hier, io_bus); 380} 381 382REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) 383