tsunami_pchip.cc revision 909
19665Sandreas.hansson@arm.com/* 29520SN/A * Copyright (c) 2004 The Regents of The University of Michigan 39520SN/A * All rights reserved. 49520SN/A * 59520SN/A * Redistribution and use in source and binary forms, with or without 69520SN/A * modification, are permitted provided that the following conditions are 79520SN/A * met: redistributions of source code must retain the above copyright 89520SN/A * notice, this list of conditions and the following disclaimer; 99520SN/A * redistributions in binary form must reproduce the above copyright 109520SN/A * notice, this list of conditions and the following disclaimer in the 119520SN/A * documentation and/or other materials provided with the distribution; 129520SN/A * neither the name of the copyright holders nor the names of its 139520SN/A * contributors may be used to endorse or promote products derived from 149520SN/A * this software without specific prior written permission. 159520SN/A * 169520SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179520SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 189520SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 199520SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 209520SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 219520SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 229520SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239520SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249520SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259520SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 269520SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279520SN/A */ 289520SN/A 299520SN/A/* @file 309520SN/A * Tsunami PChip (pci) 319520SN/A */ 329520SN/A 339520SN/A#include <deque> 349520SN/A#include <string> 359520SN/A#include <vector> 369520SN/A 379665Sandreas.hansson@arm.com#include "base/trace.hh" 389520SN/A#include "dev/tsunami_pchip.hh" 399520SN/A#include "dev/tsunamireg.h" 409520SN/A#include "dev/tsunami.hh" 419520SN/A#include "mem/bus/bus.hh" 429520SN/A#include "mem/bus/pio_interface.hh" 439520SN/A#include "mem/bus/pio_interface_impl.hh" 449665Sandreas.hansson@arm.com#include "mem/functional_mem/memory_control.hh" 459665Sandreas.hansson@arm.com#include "mem/functional_mem/physical_memory.hh" 469665Sandreas.hansson@arm.com#include "sim/builder.hh" 479520SN/A#include "sim/system.hh" 489665Sandreas.hansson@arm.com 499665Sandreas.hansson@arm.comusing namespace std; 509520SN/A 519520SN/ATsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, 529520SN/A MemoryController *mmu, HierParams *hier, 539520SN/A Bus *bus) 549665Sandreas.hansson@arm.com : PioDevice(name), addr(a), tsunami(t) 559665Sandreas.hansson@arm.com{ 569520SN/A mmu->add_child(this, Range<Addr>(addr, addr + size)); 579520SN/A 589520SN/A for (int i = 0; i < 4; i++) { 599520SN/A wsba[i] = 0; 6010789Sandreas.hansson@arm.com wsm[i] = 0; 619520SN/A tba[i] = 0; 629520SN/A } 6310789Sandreas.hansson@arm.com 649665Sandreas.hansson@arm.com if (bus) { 659520SN/A pioInterface = newPioInterface(name, hier, bus, this, 669665Sandreas.hansson@arm.com &TsunamiPChip::cacheAccess); 679520SN/A pioInterface->addAddrRange(addr, addr + size - 1); 689520SN/A } 699665Sandreas.hansson@arm.com 7010789Sandreas.hansson@arm.com 719520SN/A // initialize pchip control register 729665Sandreas.hansson@arm.com pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); 739520SN/A 749665Sandreas.hansson@arm.com //Set back pointer in tsunami 759520SN/A tsunami->pchip = this; 769520SN/A} 779520SN/A 789520SN/AFault 799520SN/ATsunamiPChip::read(MemReqPtr &req, uint8_t *data) 809520SN/A{ 819520SN/A DPRINTF(Tsunami, "read va=%#x size=%d\n", 829520SN/A req->vaddr, req->size); 839520SN/A 849665Sandreas.hansson@arm.com Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 859665Sandreas.hansson@arm.com 8610789Sandreas.hansson@arm.com switch (req->size) { 879520SN/A 889665Sandreas.hansson@arm.com case sizeof(uint64_t): 899665Sandreas.hansson@arm.com switch(daddr) { 909665Sandreas.hansson@arm.com case TSDEV_PC_WSBA0: 919520SN/A *(uint64_t*)data = wsba[0]; 9210675Sandreas.hansson@arm.com return No_Fault; 9310442Snilay@cs.wisc.edu case TSDEV_PC_WSBA1: 9410442Snilay@cs.wisc.edu *(uint64_t*)data = wsba[1]; 9510442Snilay@cs.wisc.edu return No_Fault; 9610442Snilay@cs.wisc.edu case TSDEV_PC_WSBA2: 9710442Snilay@cs.wisc.edu *(uint64_t*)data = wsba[2]; 9810442Snilay@cs.wisc.edu return No_Fault; 9910442Snilay@cs.wisc.edu case TSDEV_PC_WSBA3: 10010675Sandreas.hansson@arm.com *(uint64_t*)data = wsba[3]; 10110442Snilay@cs.wisc.edu return No_Fault; 10210677Sandreas.hansson@arm.com case TSDEV_PC_WSM0: 10310677Sandreas.hansson@arm.com *(uint64_t*)data = wsm[0]; 10410677Sandreas.hansson@arm.com return No_Fault; 10510677Sandreas.hansson@arm.com case TSDEV_PC_WSM1: 10610677Sandreas.hansson@arm.com *(uint64_t*)data = wsm[1]; 10710677Sandreas.hansson@arm.com return No_Fault; 10810677Sandreas.hansson@arm.com case TSDEV_PC_WSM2: 10910442Snilay@cs.wisc.edu *(uint64_t*)data = wsm[2]; 11010442Snilay@cs.wisc.edu return No_Fault; 11110442Snilay@cs.wisc.edu case TSDEV_PC_WSM3: 11210442Snilay@cs.wisc.edu *(uint64_t*)data = wsm[3]; 11310442Snilay@cs.wisc.edu return No_Fault; 11410442Snilay@cs.wisc.edu case TSDEV_PC_TBA0: 11510442Snilay@cs.wisc.edu *(uint64_t*)data = tba[0]; 11610442Snilay@cs.wisc.edu return No_Fault; 11710442Snilay@cs.wisc.edu case TSDEV_PC_TBA1: 11810442Snilay@cs.wisc.edu *(uint64_t*)data = tba[1]; 11910442Snilay@cs.wisc.edu return No_Fault; 12010442Snilay@cs.wisc.edu case TSDEV_PC_TBA2: 12110442Snilay@cs.wisc.edu *(uint64_t*)data = tba[2]; 12210442Snilay@cs.wisc.edu return No_Fault; 12310442Snilay@cs.wisc.edu case TSDEV_PC_TBA3: 12410442Snilay@cs.wisc.edu *(uint64_t*)data = tba[3]; 12510442Snilay@cs.wisc.edu return No_Fault; 12610442Snilay@cs.wisc.edu case TSDEV_PC_PCTL: 12710442Snilay@cs.wisc.edu *(uint64_t*)data = pctl; 12810442Snilay@cs.wisc.edu return No_Fault; 12910442Snilay@cs.wisc.edu case TSDEV_PC_PLAT: 13010675Sandreas.hansson@arm.com panic("PC_PLAT not implemented\n"); 13110442Snilay@cs.wisc.edu case TSDEV_PC_RES: 13210442Snilay@cs.wisc.edu panic("PC_RES not implemented\n"); 13310442Snilay@cs.wisc.edu case TSDEV_PC_PERROR: 13410442Snilay@cs.wisc.edu *(uint64_t*)data = 0x00; 13510442Snilay@cs.wisc.edu return No_Fault; 13610675Sandreas.hansson@arm.com case TSDEV_PC_PERRMASK: 13710677Sandreas.hansson@arm.com *(uint64_t*)data = 0x00; 13810677Sandreas.hansson@arm.com return No_Fault; 13910442Snilay@cs.wisc.edu case TSDEV_PC_PERRSET: 14010442Snilay@cs.wisc.edu panic("PC_PERRSET not implemented\n"); 14110442Snilay@cs.wisc.edu case TSDEV_PC_TLBIV: 14210442Snilay@cs.wisc.edu panic("PC_TLBIV not implemented\n"); 1439836Sandreas.hansson@arm.com case TSDEV_PC_TLBIA: 1449836Sandreas.hansson@arm.com *(uint64_t*)data = 0x00; // shouldn't be readable, but linux 1459836Sandreas.hansson@arm.com return No_Fault; 1469836Sandreas.hansson@arm.com case TSDEV_PC_PMONCTL: 1479836Sandreas.hansson@arm.com panic("PC_PMONCTL not implemented\n"); 1489836Sandreas.hansson@arm.com case TSDEV_PC_PMONCNT: 1499836Sandreas.hansson@arm.com panic("PC_PMONCTN not implemented\n"); 1509836Sandreas.hansson@arm.com default: 1519836Sandreas.hansson@arm.com panic("Default in PChip Read reached reading 0x%x\n", daddr); 1529836Sandreas.hansson@arm.com 1539836Sandreas.hansson@arm.com } // uint64_t 15410780SCurtis.Dunham@arm.com 15510780SCurtis.Dunham@arm.com break; 15610780SCurtis.Dunham@arm.com case sizeof(uint32_t): 15710780SCurtis.Dunham@arm.com case sizeof(uint16_t): 15810780SCurtis.Dunham@arm.com case sizeof(uint8_t): 15910780SCurtis.Dunham@arm.com default: 16010780SCurtis.Dunham@arm.com panic("invalid access size(?) for tsunami register!\n\n"); 16110780SCurtis.Dunham@arm.com } 1629836Sandreas.hansson@arm.com DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); 1639836Sandreas.hansson@arm.com 1649836Sandreas.hansson@arm.com return No_Fault; 1659836Sandreas.hansson@arm.com} 1669836Sandreas.hansson@arm.com 1679836Sandreas.hansson@arm.comFault 16810442Snilay@cs.wisc.eduTsunamiPChip::write(MemReqPtr &req, const uint8_t *data) 1699836Sandreas.hansson@arm.com{ 1709836Sandreas.hansson@arm.com DPRINTF(Tsunami, "write - va=%#x size=%d \n", 1719836Sandreas.hansson@arm.com req->vaddr, req->size); 17210675Sandreas.hansson@arm.com 17310675Sandreas.hansson@arm.com Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 17410675Sandreas.hansson@arm.com 17510675Sandreas.hansson@arm.com switch (req->size) { 17610675Sandreas.hansson@arm.com 17710675Sandreas.hansson@arm.com case sizeof(uint64_t): 1789836Sandreas.hansson@arm.com switch(daddr) { 1799836Sandreas.hansson@arm.com case TSDEV_PC_WSBA0: 1809836Sandreas.hansson@arm.com wsba[0] = *(uint64_t*)data; 1819836Sandreas.hansson@arm.com return No_Fault; 1829836Sandreas.hansson@arm.com case TSDEV_PC_WSBA1: 18310620Sandreas.hansson@arm.com wsba[1] = *(uint64_t*)data; 18410675Sandreas.hansson@arm.com return No_Fault; 18510620Sandreas.hansson@arm.com case TSDEV_PC_WSBA2: 18610620Sandreas.hansson@arm.com wsba[2] = *(uint64_t*)data; 18710620Sandreas.hansson@arm.com return No_Fault; 18810620Sandreas.hansson@arm.com case TSDEV_PC_WSBA3: 18910620Sandreas.hansson@arm.com wsba[3] = *(uint64_t*)data; 19010620Sandreas.hansson@arm.com return No_Fault; 19110620Sandreas.hansson@arm.com case TSDEV_PC_WSM0: 1929836Sandreas.hansson@arm.com wsm[0] = *(uint64_t*)data; 1939836Sandreas.hansson@arm.com return No_Fault; 1949836Sandreas.hansson@arm.com case TSDEV_PC_WSM1: 1959836Sandreas.hansson@arm.com wsm[1] = *(uint64_t*)data; 19610041Snilay@cs.wisc.edu return No_Fault; 1979836Sandreas.hansson@arm.com case TSDEV_PC_WSM2: 198 wsm[2] = *(uint64_t*)data; 199 return No_Fault; 200 case TSDEV_PC_WSM3: 201 wsm[3] = *(uint64_t*)data; 202 return No_Fault; 203 case TSDEV_PC_TBA0: 204 tba[0] = *(uint64_t*)data; 205 return No_Fault; 206 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