tsunami_pchip.cc revision 2107
14123Sbinkertn@umich.edu/* 24123Sbinkertn@umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 34123Sbinkertn@umich.edu * All rights reserved. 44123Sbinkertn@umich.edu * 54123Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without 64123Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are 74123Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright 84123Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer; 94123Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright 104123Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the 114123Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution; 124123Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its 134123Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from 144123Sbinkertn@umich.edu * this software without specific prior written permission. 154123Sbinkertn@umich.edu * 164123Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174123Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184123Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194123Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204123Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214123Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224123Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234123Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244123Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254123Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264123Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274123Sbinkertn@umich.edu */ 284123Sbinkertn@umich.edu 294123Sbinkertn@umich.edu/** @file 304123Sbinkertn@umich.edu * Tsunami PChip (pci) 314123Sbinkertn@umich.edu */ 324123Sbinkertn@umich.edu 334123Sbinkertn@umich.edu#include <deque> 346216Snate@binkert.org#include <string> 354123Sbinkertn@umich.edu#include <vector> 369356Snilay@cs.wisc.edu 374123Sbinkertn@umich.edu#include "base/trace.hh" 384123Sbinkertn@umich.edu#include "dev/tsunami_pchip.hh" 394123Sbinkertn@umich.edu#include "dev/tsunamireg.h" 406216Snate@binkert.org#include "dev/tsunami.hh" 414123Sbinkertn@umich.edu#include "mem/bus/bus.hh" 424123Sbinkertn@umich.edu#include "mem/bus/pio_interface.hh" 434123Sbinkertn@umich.edu#include "mem/bus/pio_interface_impl.hh" 444123Sbinkertn@umich.edu#include "mem/functional/memory_control.hh" 454123Sbinkertn@umich.edu#include "mem/functional/physical.hh" 464123Sbinkertn@umich.edu#include "sim/builder.hh" 474123Sbinkertn@umich.edu#include "sim/system.hh" 484123Sbinkertn@umich.edu 494123Sbinkertn@umich.eduusing namespace std; 507823Ssteve.reinhardt@amd.com//Should this be AlphaISA? 514123Sbinkertn@umich.eduusing namespace TheISA; 529174Satgutier@umich.edu 539174Satgutier@umich.eduTsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, 549174Satgutier@umich.edu MemoryController *mmu, HierParams *hier, 554123Sbinkertn@umich.edu Bus *pio_bus, Tick pio_latency) 564123Sbinkertn@umich.edu : PioDevice(name, t), addr(a), tsunami(t) 575606Snate@binkert.org{ 585606Snate@binkert.org mmu->add_child(this, RangeSize(addr, size)); 595606Snate@binkert.org 604123Sbinkertn@umich.edu for (int i = 0; i < 4; i++) { 614123Sbinkertn@umich.edu wsba[i] = 0; 624123Sbinkertn@umich.edu wsm[i] = 0; 634123Sbinkertn@umich.edu tba[i] = 0; 644123Sbinkertn@umich.edu } 657823Ssteve.reinhardt@amd.com 664123Sbinkertn@umich.edu if (pio_bus) { 674123Sbinkertn@umich.edu pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this, 684123Sbinkertn@umich.edu &TsunamiPChip::cacheAccess); 694123Sbinkertn@umich.edu pioInterface->addAddrRange(RangeSize(addr, size)); 704123Sbinkertn@umich.edu pioLatency = pio_latency * pio_bus->clockRate; 714123Sbinkertn@umich.edu } 724123Sbinkertn@umich.edu 734123Sbinkertn@umich.edu 744123Sbinkertn@umich.edu // initialize pchip control register 754123Sbinkertn@umich.edu pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36); 764123Sbinkertn@umich.edu 774123Sbinkertn@umich.edu //Set back pointer in tsunami 784123Sbinkertn@umich.edu tsunami->pchip = this; 794123Sbinkertn@umich.edu} 804123Sbinkertn@umich.edu 815606Snate@binkert.orgFault * 825823Ssaidi@eecs.umich.eduTsunamiPChip::read(MemReqPtr &req, uint8_t *data) 834123Sbinkertn@umich.edu{ 844123Sbinkertn@umich.edu DPRINTF(Tsunami, "read va=%#x size=%d\n", 854123Sbinkertn@umich.edu req->vaddr, req->size); 864123Sbinkertn@umich.edu 874123Sbinkertn@umich.edu Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; 884123Sbinkertn@umich.edu 894123Sbinkertn@umich.edu switch (req->size) { 904123Sbinkertn@umich.edu 917822Ssteve.reinhardt@amd.com case sizeof(uint64_t): 924123Sbinkertn@umich.edu switch(daddr) { 934123Sbinkertn@umich.edu case TSDEV_PC_WSBA0: 944123Sbinkertn@umich.edu *(uint64_t*)data = wsba[0]; 954123Sbinkertn@umich.edu return NoFault; 964123Sbinkertn@umich.edu case TSDEV_PC_WSBA1: 974123Sbinkertn@umich.edu *(uint64_t*)data = wsba[1]; 984123Sbinkertn@umich.edu return NoFault; 994123Sbinkertn@umich.edu case TSDEV_PC_WSBA2: 1004123Sbinkertn@umich.edu *(uint64_t*)data = wsba[2]; 1014123Sbinkertn@umich.edu return NoFault; 1024123Sbinkertn@umich.edu case TSDEV_PC_WSBA3: 1034123Sbinkertn@umich.edu *(uint64_t*)data = wsba[3]; 1044123Sbinkertn@umich.edu return NoFault; 1054123Sbinkertn@umich.edu case TSDEV_PC_WSM0: 1064123Sbinkertn@umich.edu *(uint64_t*)data = wsm[0]; 1074123Sbinkertn@umich.edu return NoFault; 1084123Sbinkertn@umich.edu case TSDEV_PC_WSM1: 1094123Sbinkertn@umich.edu *(uint64_t*)data = wsm[1]; 1104123Sbinkertn@umich.edu return NoFault; 1114123Sbinkertn@umich.edu case TSDEV_PC_WSM2: 1124123Sbinkertn@umich.edu *(uint64_t*)data = wsm[2]; 1134123Sbinkertn@umich.edu return NoFault; 1144123Sbinkertn@umich.edu case TSDEV_PC_WSM3: 1154123Sbinkertn@umich.edu *(uint64_t*)data = wsm[3]; 1164123Sbinkertn@umich.edu return NoFault; 117 case TSDEV_PC_TBA0: 118 *(uint64_t*)data = tba[0]; 119 return NoFault; 120 case TSDEV_PC_TBA1: 121 *(uint64_t*)data = tba[1]; 122 return NoFault; 123 case TSDEV_PC_TBA2: 124 *(uint64_t*)data = tba[2]; 125 return NoFault; 126 case TSDEV_PC_TBA3: 127 *(uint64_t*)data = tba[3]; 128 return NoFault; 129 case TSDEV_PC_PCTL: 130 *(uint64_t*)data = pctl; 131 return NoFault; 132 case TSDEV_PC_PLAT: 133 panic("PC_PLAT not implemented\n"); 134 case TSDEV_PC_RES: 135 panic("PC_RES not implemented\n"); 136 case TSDEV_PC_PERROR: 137 *(uint64_t*)data = 0x00; 138 return NoFault; 139 case TSDEV_PC_PERRMASK: 140 *(uint64_t*)data = 0x00; 141 return NoFault; 142 case TSDEV_PC_PERRSET: 143 panic("PC_PERRSET not implemented\n"); 144 case TSDEV_PC_TLBIV: 145 panic("PC_TLBIV not implemented\n"); 146 case TSDEV_PC_TLBIA: 147 *(uint64_t*)data = 0x00; // shouldn't be readable, but linux 148 return NoFault; 149 case TSDEV_PC_PMONCTL: 150 panic("PC_PMONCTL not implemented\n"); 151 case TSDEV_PC_PMONCNT: 152 panic("PC_PMONCTN not implemented\n"); 153 default: 154 panic("Default in PChip Read reached reading 0x%x\n", daddr); 155 156 } // uint64_t 157 158 break; 159 case sizeof(uint32_t): 160 case sizeof(uint16_t): 161 case sizeof(uint8_t): 162 default: 163 panic("invalid access size(?) for tsunami register!\n\n"); 164 } 165 DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); 166 167 return NoFault; 168} 169 170Fault * 171TsunamiPChip::write(MemReqPtr &req, const uint8_t *data) 172{ 173 DPRINTF(Tsunami, "write - va=%#x size=%d \n", 174 req->vaddr, req->size); 175 176 Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6; 177 178 switch (req->size) { 179 180 case sizeof(uint64_t): 181 switch(daddr) { 182 case TSDEV_PC_WSBA0: 183 wsba[0] = *(uint64_t*)data; 184 return NoFault; 185 case TSDEV_PC_WSBA1: 186 wsba[1] = *(uint64_t*)data; 187 return NoFault; 188 case TSDEV_PC_WSBA2: 189 wsba[2] = *(uint64_t*)data; 190 return NoFault; 191 case TSDEV_PC_WSBA3: 192 wsba[3] = *(uint64_t*)data; 193 return NoFault; 194 case TSDEV_PC_WSM0: 195 wsm[0] = *(uint64_t*)data; 196 return NoFault; 197 case TSDEV_PC_WSM1: 198 wsm[1] = *(uint64_t*)data; 199 return NoFault; 200 case TSDEV_PC_WSM2: 201 wsm[2] = *(uint64_t*)data; 202 return NoFault; 203 case TSDEV_PC_WSM3: 204 wsm[3] = *(uint64_t*)data; 205 return NoFault; 206 case TSDEV_PC_TBA0: 207 tba[0] = *(uint64_t*)data; 208 return NoFault; 209 case TSDEV_PC_TBA1: 210 tba[1] = *(uint64_t*)data; 211 return NoFault; 212 case TSDEV_PC_TBA2: 213 tba[2] = *(uint64_t*)data; 214 return NoFault; 215 case TSDEV_PC_TBA3: 216 tba[3] = *(uint64_t*)data; 217 return NoFault; 218 case TSDEV_PC_PCTL: 219 pctl = *(uint64_t*)data; 220 return NoFault; 221 case TSDEV_PC_PLAT: 222 panic("PC_PLAT not implemented\n"); 223 case TSDEV_PC_RES: 224 panic("PC_RES not implemented\n"); 225 case TSDEV_PC_PERROR: 226 return NoFault; 227 case TSDEV_PC_PERRMASK: 228 panic("PC_PERRMASK not implemented\n"); 229 case TSDEV_PC_PERRSET: 230 panic("PC_PERRSET not implemented\n"); 231 case TSDEV_PC_TLBIV: 232 panic("PC_TLBIV not implemented\n"); 233 case TSDEV_PC_TLBIA: 234 return NoFault; // value ignored, supposted to invalidate SG TLB 235 case TSDEV_PC_PMONCTL: 236 panic("PC_PMONCTL not implemented\n"); 237 case TSDEV_PC_PMONCNT: 238 panic("PC_PMONCTN not implemented\n"); 239 default: 240 panic("Default in PChip Read reached reading 0x%x\n", daddr); 241 242 } // uint64_t 243 244 break; 245 case sizeof(uint32_t): 246 case sizeof(uint16_t): 247 case sizeof(uint8_t): 248 default: 249 panic("invalid access size(?) for tsunami register!\n\n"); 250 } 251 252 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); 253 254 return NoFault; 255} 256 257#define DMA_ADDR_MASK ULL(0x3ffffffff) 258 259Addr 260TsunamiPChip::translatePciToDma(Addr busAddr) 261{ 262 // compare the address to the window base registers 263 uint64_t tbaMask = 0; 264 uint64_t baMask = 0; 265 266 uint64_t windowMask = 0; 267 uint64_t windowBase = 0; 268 269 uint64_t pteEntry = 0; 270 271 Addr pteAddr; 272 Addr dmaAddr; 273 274#if 0 275 DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr); 276 for (int i = 0; i < 4; i++) { 277 DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n", 278 i, wsba[i], wsm[i]); 279 280 windowBase = wsba[i]; 281 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 282 283 if ((busAddr & windowMask) == (windowBase & windowMask)) { 284 DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n", 285 i, windowBase, windowMask, (busAddr & windowMask), 286 (windowBase & windowMask)); 287 } 288 } 289#endif 290 291 for (int i = 0; i < 4; i++) { 292 293 windowBase = wsba[i]; 294 windowMask = ~wsm[i] & (ULL(0xfff) << 20); 295 296 if ((busAddr & windowMask) == (windowBase & windowMask)) { 297 298 if (wsba[i] & 0x1) { // see if enabled 299 if (wsba[i] & 0x2) { // see if SG bit is set 300 /** @todo 301 This currently is faked by just doing a direct 302 read from memory, however, to be realistic, this 303 needs to actually do a bus transaction. The process 304 is explained in the tsunami documentation on page 305 10-12 and basically munges the address to look up a 306 PTE from a table in memory and then uses that mapping 307 to create an address for the SG page 308 */ 309 310 tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff)); 311 baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13); 312 pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 313 314 memcpy((void *)&pteEntry, 315 tsunami->system-> 316 physmem->dma_addr(pteAddr, sizeof(uint64_t)), 317 sizeof(uint64_t)); 318 319 dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff)); 320 321 } else { 322 baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff); 323 tbaMask = ~baMask; 324 dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 325 } 326 327 return (dmaAddr & DMA_ADDR_MASK); 328 } 329 } 330 } 331 332 // if no match was found, then return the original address 333 return busAddr; 334} 335 336void 337TsunamiPChip::serialize(std::ostream &os) 338{ 339 SERIALIZE_SCALAR(pctl); 340 SERIALIZE_ARRAY(wsba, 4); 341 SERIALIZE_ARRAY(wsm, 4); 342 SERIALIZE_ARRAY(tba, 4); 343} 344 345void 346TsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 347{ 348 UNSERIALIZE_SCALAR(pctl); 349 UNSERIALIZE_ARRAY(wsba, 4); 350 UNSERIALIZE_ARRAY(wsm, 4); 351 UNSERIALIZE_ARRAY(tba, 4); 352} 353 354Tick 355TsunamiPChip::cacheAccess(MemReqPtr &req) 356{ 357 return curTick + pioLatency; 358} 359 360BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 361 362 SimObjectParam<Tsunami *> tsunami; 363 SimObjectParam<MemoryController *> mmu; 364 Param<Addr> addr; 365 SimObjectParam<Bus*> pio_bus; 366 Param<Tick> pio_latency; 367 SimObjectParam<HierParams *> hier; 368 369END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 370 371BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 372 373 INIT_PARAM(tsunami, "Tsunami"), 374 INIT_PARAM(mmu, "Memory Controller"), 375 INIT_PARAM(addr, "Device Address"), 376 INIT_PARAM_DFLT(pio_bus, "The IO Bus to attach to", NULL), 377 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 378 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams) 379 380END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 381 382CREATE_SIM_OBJECT(TsunamiPChip) 383{ 384 return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu, hier, 385 pio_bus, pio_latency); 386} 387 388REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) 389