tsunami_pchip.cc revision 892
1360SN/A/* 21458SN/A * Copyright (c) 2004 The Regents of The University of Michigan 3360SN/A * All rights reserved. 4360SN/A * 5360SN/A * Redistribution and use in source and binary forms, with or without 6360SN/A * modification, are permitted provided that the following conditions are 7360SN/A * met: redistributions of source code must retain the above copyright 8360SN/A * notice, this list of conditions and the following disclaimer; 9360SN/A * redistributions in binary form must reproduce the above copyright 10360SN/A * notice, this list of conditions and the following disclaimer in the 11360SN/A * documentation and/or other materials provided with the distribution; 12360SN/A * neither the name of the copyright holders nor the names of its 13360SN/A * contributors may be used to endorse or promote products derived from 14360SN/A * this software without specific prior written permission. 15360SN/A * 16360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 292665Ssaidi@eecs.umich.edu/* @file 30360SN/A * Tsunami PChip (pci) 31360SN/A */ 3211793Sbrandon.potter@amd.com 3311793Sbrandon.potter@amd.com#include <deque> 342093SN/A#include <string> 35360SN/A#include <vector> 36360SN/A 376712Snate@binkert.org#include "base/trace.hh" 386712Snate@binkert.org#include "cpu/exec_context.hh" 39360SN/A#include "dev/console.hh" 40360SN/A#include "dev/etherdev.hh" 417680Sgblack@eecs.umich.edu#include "dev/scsi_ctrl.hh" 422474SN/A#include "dev/tlaser_clock.hh" 43360SN/A#include "dev/tsunami_pchip.hh" 446658Snate@binkert.org#include "dev/tsunamireg.h" 458229Snate@binkert.org#include "dev/tsunami.hh" 462680Sktlim@umich.edu#include "mem/functional_mem/memory_control.hh" 4711380Salexandru.dutu@amd.com#include "mem/functional_mem/physical_memory.hh" 488232Snate@binkert.org#include "sim/builder.hh" 492474SN/A#include "sim/system.hh" 50360SN/A 518229Snate@binkert.orgusing namespace std; 526029Ssteve.reinhardt@amd.com 53360SN/ATsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a, 54360SN/A MemoryController *mmu) 552107SN/A : FunctionalMemory(name), addr(a), tsunami(t) 56360SN/A{ 57360SN/A mmu->add_child(this, Range<Addr>(addr, addr + size)); 583114Sgblack@eecs.umich.edu 59360SN/A for (int i = 0; i < 4; i++) { 6011380Salexandru.dutu@amd.com wsba[i] = 0; 6110253Ssteve.reinhardt@amd.com wsm[i] = 0; 6211380Salexandru.dutu@amd.com tba[i] = 0; 6310253Ssteve.reinhardt@amd.com } 6410253Ssteve.reinhardt@amd.com 6510253Ssteve.reinhardt@amd.com //Set back pointer in tsunami 6611380Salexandru.dutu@amd.com tsunami->pchip = this; 6710253Ssteve.reinhardt@amd.com} 6810253Ssteve.reinhardt@amd.com 6911380Salexandru.dutu@amd.comFault 7011380Salexandru.dutu@amd.comTsunamiPChip::read(MemReqPtr &req, uint8_t *data) 7111380Salexandru.dutu@amd.com{ 7211380Salexandru.dutu@amd.com DPRINTF(Tsunami, "read va=%#x size=%d\n", 7311380Salexandru.dutu@amd.com req->vaddr, req->size); 7411380Salexandru.dutu@amd.com 7511380Salexandru.dutu@amd.com Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 7610253Ssteve.reinhardt@amd.com 77360SN/A switch (req->size) { 782680Sktlim@umich.edu 79360SN/A case sizeof(uint64_t): 8010500Ssteve.reinhardt@amd.com switch(daddr) { 8111380Salexandru.dutu@amd.com case TSDEV_PC_WSBA0: 8210500Ssteve.reinhardt@amd.com *(uint64_t*)data = wsba[0]; 8311380Salexandru.dutu@amd.com return No_Fault; 8411380Salexandru.dutu@amd.com case TSDEV_PC_WSBA1: 8510500Ssteve.reinhardt@amd.com *(uint64_t*)data = wsba[1]; 86360SN/A return No_Fault; 8710500Ssteve.reinhardt@amd.com case TSDEV_PC_WSBA2: 885958Sgblack@eecs.umich.edu *(uint64_t*)data = wsba[2]; 89360SN/A return No_Fault; 90360SN/A case TSDEV_PC_WSBA3: 91360SN/A *(uint64_t*)data = wsba[3]; 921450SN/A return No_Fault; 933114Sgblack@eecs.umich.edu case TSDEV_PC_WSM0: 942680Sktlim@umich.edu *(uint64_t*)data = wsm[0]; 95360SN/A return No_Fault; 961969SN/A case TSDEV_PC_WSM1: 972484SN/A *(uint64_t*)data = wsm[1]; 982484SN/A return No_Fault; 99360SN/A case TSDEV_PC_WSM2: 100360SN/A *(uint64_t*)data = wsm[2]; 101360SN/A return No_Fault; 1021450SN/A case TSDEV_PC_WSM3: 1033114Sgblack@eecs.umich.edu *(uint64_t*)data = wsm[3]; 1042680Sktlim@umich.edu return No_Fault; 105360SN/A case TSDEV_PC_TBA0: 1066701Sgblack@eecs.umich.edu *(uint64_t*)data = tba[0]; 10710831Ssteve.reinhardt@amd.com return No_Fault; 108360SN/A case TSDEV_PC_TBA1: 10910831Ssteve.reinhardt@amd.com *(uint64_t*)data = tba[1]; 11010831Ssteve.reinhardt@amd.com return No_Fault; 11110831Ssteve.reinhardt@amd.com case TSDEV_PC_TBA2: 112360SN/A *(uint64_t*)data = tba[2]; 11310831Ssteve.reinhardt@amd.com return No_Fault; 11410831Ssteve.reinhardt@amd.com case TSDEV_PC_TBA3: 11510831Ssteve.reinhardt@amd.com *(uint64_t*)data = tba[3]; 116360SN/A return No_Fault; 11710831Ssteve.reinhardt@amd.com case TSDEV_PC_PCTL: 11810831Ssteve.reinhardt@amd.com // might want to change the clock?? 1198149SChris.Emmons@ARM.com *(uint64_t*)data = 0x00; // try this 1208149SChris.Emmons@ARM.com return No_Fault; 1218149SChris.Emmons@ARM.com case TSDEV_PC_PLAT: 1228149SChris.Emmons@ARM.com panic("PC_PLAT not implemented\n"); 1238149SChris.Emmons@ARM.com case TSDEV_PC_RES: 1248149SChris.Emmons@ARM.com panic("PC_RES not implemented\n"); 1253114Sgblack@eecs.umich.edu case TSDEV_PC_PERROR: 1262680Sktlim@umich.edu *(uint64_t*)data = 0x00; 127360SN/A return No_Fault; 1286029Ssteve.reinhardt@amd.com case TSDEV_PC_PERRMASK: 1296029Ssteve.reinhardt@amd.com *(uint64_t*)data = 0x00; 1306701Sgblack@eecs.umich.edu return No_Fault; 1315958Sgblack@eecs.umich.edu case TSDEV_PC_PERRSET: 1326701Sgblack@eecs.umich.edu panic("PC_PERRSET not implemented\n"); 1336029Ssteve.reinhardt@amd.com case TSDEV_PC_TLBIV: 1346029Ssteve.reinhardt@amd.com panic("PC_TLBIV not implemented\n"); 1356029Ssteve.reinhardt@amd.com case TSDEV_PC_TLBIA: 1362834Sksewell@umich.edu *(uint64_t*)data = 0x00; // shouldn't be readable, but linux 137360SN/A return No_Fault; 1381458SN/A case TSDEV_PC_PMONCTL: 139360SN/A panic("PC_PMONCTL not implemented\n"); 140360SN/A case TSDEV_PC_PMONCNT: 141360SN/A panic("PC_PMONCTN not implemented\n"); 1421450SN/A default: 1436109Ssanchezd@stanford.edu panic("Default in PChip Read reached reading 0x%x\n", daddr); 1446109Ssanchezd@stanford.edu 1456109Ssanchezd@stanford.edu } // uint64_t 14610483Swiseveri@student.ethz.ch 14710483Swiseveri@student.ethz.ch break; 14810483Swiseveri@student.ethz.ch case sizeof(uint32_t): 14910483Swiseveri@student.ethz.ch case sizeof(uint16_t): 15010483Swiseveri@student.ethz.ch case sizeof(uint8_t): 15110483Swiseveri@student.ethz.ch default: 15210483Swiseveri@student.ethz.ch panic("invalid access size(?) for tsunami register!\n\n"); 15310483Swiseveri@student.ethz.ch } 15410483Swiseveri@student.ethz.ch DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size); 15510483Swiseveri@student.ethz.ch 15610483Swiseveri@student.ethz.ch return No_Fault; 1576109Ssanchezd@stanford.edu} 1586109Ssanchezd@stanford.edu 1596109Ssanchezd@stanford.eduFault 1606109Ssanchezd@stanford.eduTsunamiPChip::write(MemReqPtr &req, const uint8_t *data) 1616109Ssanchezd@stanford.edu{ 1626109Ssanchezd@stanford.edu DPRINTF(Tsunami, "write - va=%#x size=%d \n", 1633114Sgblack@eecs.umich.edu req->vaddr, req->size); 164360SN/A 16510318Sandreas.hansson@arm.com Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6; 166360SN/A 167360SN/A switch (req->size) { 168360SN/A 1691450SN/A case sizeof(uint64_t): 1705748SSteve.Reinhardt@amd.com switch(daddr) { 171360SN/A case TSDEV_PC_WSBA0: 172360SN/A wsba[0] = *(uint64_t*)data; 1736701Sgblack@eecs.umich.edu return No_Fault; 1746701Sgblack@eecs.umich.edu case TSDEV_PC_WSBA1: 1755748SSteve.Reinhardt@amd.com wsba[1] = *(uint64_t*)data; 1765748SSteve.Reinhardt@amd.com return No_Fault; 1775748SSteve.Reinhardt@amd.com case TSDEV_PC_WSBA2: 1785748SSteve.Reinhardt@amd.com wsba[2] = *(uint64_t*)data; 1795748SSteve.Reinhardt@amd.com return No_Fault; 1805748SSteve.Reinhardt@amd.com case TSDEV_PC_WSBA3: 1815748SSteve.Reinhardt@amd.com wsba[3] = *(uint64_t*)data; 1825748SSteve.Reinhardt@amd.com return No_Fault; 1832474SN/A case TSDEV_PC_WSM0: 18410318Sandreas.hansson@arm.com wsm[0] = *(uint64_t*)data; 1855748SSteve.Reinhardt@amd.com return No_Fault; 18610318Sandreas.hansson@arm.com case TSDEV_PC_WSM1: 1876687Stjones1@inf.ed.ac.uk wsm[1] = *(uint64_t*)data; 1886687Stjones1@inf.ed.ac.uk return No_Fault; 1896687Stjones1@inf.ed.ac.uk case TSDEV_PC_WSM2: 1906687Stjones1@inf.ed.ac.uk wsm[2] = *(uint64_t*)data; 1918852Sandreas.hansson@arm.com return No_Fault; 1926687Stjones1@inf.ed.ac.uk case TSDEV_PC_WSM3: 1936687Stjones1@inf.ed.ac.uk wsm[3] = *(uint64_t*)data; 19410318Sandreas.hansson@arm.com return No_Fault; 1956687Stjones1@inf.ed.ac.uk case TSDEV_PC_TBA0: 1968852Sandreas.hansson@arm.com tba[0] = *(uint64_t*)data; 19710318Sandreas.hansson@arm.com return No_Fault; 1986687Stjones1@inf.ed.ac.uk case TSDEV_PC_TBA1: 1996687Stjones1@inf.ed.ac.uk tba[1] = *(uint64_t*)data; 2006687Stjones1@inf.ed.ac.uk return No_Fault; 20110318Sandreas.hansson@arm.com case TSDEV_PC_TBA2: 2028852Sandreas.hansson@arm.com tba[2] = *(uint64_t*)data; 2036687Stjones1@inf.ed.ac.uk return No_Fault; 2046687Stjones1@inf.ed.ac.uk case TSDEV_PC_TBA3: 2052474SN/A tba[3] = *(uint64_t*)data; 2061450SN/A return No_Fault; 2075748SSteve.Reinhardt@amd.com case TSDEV_PC_PCTL: 2085748SSteve.Reinhardt@amd.com // might want to change the clock?? 20911380Salexandru.dutu@amd.com return No_Fault; 21011380Salexandru.dutu@amd.com case TSDEV_PC_PLAT: 2111458SN/A panic("PC_PLAT not implemented\n"); 212360SN/A case TSDEV_PC_RES: 213360SN/A panic("PC_RES not implemented\n"); 214360SN/A case TSDEV_PC_PERROR: 2151450SN/A return No_Fault; 2163114Sgblack@eecs.umich.edu case TSDEV_PC_PERRMASK: 217360SN/A panic("PC_PERRMASK not implemented\n"); 2186701Sgblack@eecs.umich.edu case TSDEV_PC_PERRSET: 21910931Sbrandon.potter@amd.com panic("PC_PERRSET not implemented\n"); 22010931Sbrandon.potter@amd.com case TSDEV_PC_TLBIV: 22110932Sbrandon.potter@amd.com panic("PC_TLBIV not implemented\n"); 22210931Sbrandon.potter@amd.com case TSDEV_PC_TLBIA: 22310931Sbrandon.potter@amd.com return No_Fault; // value ignored, supposted to invalidate SG TLB 22410931Sbrandon.potter@amd.com case TSDEV_PC_PMONCTL: 2257508Stjones1@inf.ed.ac.uk panic("PC_PMONCTL not implemented\n"); 2267508Stjones1@inf.ed.ac.uk case TSDEV_PC_PMONCNT: 2277508Stjones1@inf.ed.ac.uk panic("PC_PMONCTN not implemented\n"); 2281970SN/A default: 22910932Sbrandon.potter@amd.com panic("Default in PChip Read reached reading 0x%x\n", daddr); 2301970SN/A 231360SN/A } // uint64_t 232360SN/A 233360SN/A break; 2341450SN/A case sizeof(uint32_t): 2353114Sgblack@eecs.umich.edu case sizeof(uint16_t): 236360SN/A case sizeof(uint8_t): 2376701Sgblack@eecs.umich.edu default: 23810931Sbrandon.potter@amd.com panic("invalid access size(?) for tsunami register!\n\n"); 2396701Sgblack@eecs.umich.edu } 2406701Sgblack@eecs.umich.edu 2416701Sgblack@eecs.umich.edu DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size); 242360SN/A 24310932Sbrandon.potter@amd.com return No_Fault; 24410931Sbrandon.potter@amd.com} 24510931Sbrandon.potter@amd.com 24610931Sbrandon.potter@amd.com#define DMA_ADDR_MASK ULL(0x3ffffffff) 24710931Sbrandon.potter@amd.com 248360SN/AAddr 24911684Snderumigny@gmail.comTsunamiPChip::translatePciToDma(Addr busAddr) 2508706Sandreas.hansson@arm.com{ 251360SN/A // compare the address to the window base registers 2521458SN/A uint64_t tbaMask = 0; 253360SN/A uint64_t baMask = 0; 254360SN/A 2551450SN/A uint64_t windowMask = 0; 2563114Sgblack@eecs.umich.edu uint64_t windowBase = 0; 257360SN/A 2586701Sgblack@eecs.umich.edu uint64_t pteEntry = 0; 25910931Sbrandon.potter@amd.com 2606701Sgblack@eecs.umich.edu Addr pteAddr; 2616701Sgblack@eecs.umich.edu Addr dmaAddr; 2626701Sgblack@eecs.umich.edu 263360SN/A for (int i = 0; i < 4; i++) { 26410932Sbrandon.potter@amd.com windowBase = wsba[i]; 26510931Sbrandon.potter@amd.com windowMask = ~wsm[i] & (0x7ff << 20); 26610931Sbrandon.potter@amd.com 26710931Sbrandon.potter@amd.com if ((busAddr & windowMask) == (windowBase & windowMask)) { 2688706Sandreas.hansson@arm.com 269360SN/A 27010931Sbrandon.potter@amd.com if (wsba[i] & 0x1) { // see if enabled 271360SN/A if (wsba[i] & 0x2) { // see if SG bit is set 27210931Sbrandon.potter@amd.com /** @todo 273360SN/A This currently is faked by just doing a direct 2741458SN/A read from memory, however, to be realistic, this 275360SN/A needs to actually do a bus transaction. The process 276360SN/A is explained in the tsunami documentation on page 277360SN/A 10-12 and basically munges the address to look up a 2781450SN/A PTE from a table in memory and then uses that mapping 2793114Sgblack@eecs.umich.edu to create an address for the SG page 280360SN/A */ 2816701Sgblack@eecs.umich.edu 28210931Sbrandon.potter@amd.com tbaMask = ~(((wsm[i] & (0x7ff << 20)) >> 10) | 0x3ff); 2836701Sgblack@eecs.umich.edu baMask = (wsm[i] & (0x7ff << 20)) | (0x7f << 13); 2846701Sgblack@eecs.umich.edu pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10); 285360SN/A 28610932Sbrandon.potter@amd.com memcpy((void *)&pteEntry, 28710931Sbrandon.potter@amd.com tsunami->system-> 28810931Sbrandon.potter@amd.com physmem->dma_addr(pteAddr, sizeof(uint64_t)), 28910931Sbrandon.potter@amd.com sizeof(uint64_t)); 29010931Sbrandon.potter@amd.com 291360SN/A dmaAddr = ((pteEntry & ~0x1) << 12) | (busAddr & 0x1fff); 2921458SN/A 293360SN/A } else { 294360SN/A baMask = (wsm[i] & (0x7ff << 20)) | 0xfffff; 295360SN/A tbaMask = ~baMask; 2961450SN/A dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask); 2974118Sgblack@eecs.umich.edu } 2984118Sgblack@eecs.umich.edu 2996701Sgblack@eecs.umich.edu return (dmaAddr & DMA_ADDR_MASK); 30010931Sbrandon.potter@amd.com } 3016701Sgblack@eecs.umich.edu } 3026701Sgblack@eecs.umich.edu } 3036701Sgblack@eecs.umich.edu 3046701Sgblack@eecs.umich.edu return 0; 3054118Sgblack@eecs.umich.edu} 30610932Sbrandon.potter@amd.com 30710931Sbrandon.potter@amd.comvoid 30810931Sbrandon.potter@amd.comTsunamiPChip::serialize(std::ostream &os) 30910931Sbrandon.potter@amd.com{ 3104118Sgblack@eecs.umich.edu SERIALIZE_ARRAY(wsba, 4); 3114118Sgblack@eecs.umich.edu SERIALIZE_ARRAY(wsm, 4); 31210931Sbrandon.potter@amd.com SERIALIZE_ARRAY(tba, 4); 3134118Sgblack@eecs.umich.edu} 3144118Sgblack@eecs.umich.edu 31511379Sbrandon.potter@amd.comvoid 3164118Sgblack@eecs.umich.eduTsunamiPChip::unserialize(Checkpoint *cp, const std::string §ion) 31711379Sbrandon.potter@amd.com{ 31811379Sbrandon.potter@amd.com UNSERIALIZE_ARRAY(wsba, 4); 31911379Sbrandon.potter@amd.com UNSERIALIZE_ARRAY(wsm, 4); 32011379Sbrandon.potter@amd.com UNSERIALIZE_ARRAY(tba, 4); 32111379Sbrandon.potter@amd.com} 3224118Sgblack@eecs.umich.edu 3234118Sgblack@eecs.umich.eduBEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 3244118Sgblack@eecs.umich.edu 3254118Sgblack@eecs.umich.edu SimObjectParam<Tsunami *> tsunami; 3263114Sgblack@eecs.umich.edu SimObjectParam<MemoryController *> mmu; 327360SN/A Param<Addr> addr; 32811383Sbrandon.potter@amd.com 32911383Sbrandon.potter@amd.comEND_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip) 33011383Sbrandon.potter@amd.com 3311458SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 332360SN/A 333360SN/A INIT_PARAM(tsunami, "Tsunami"), 334360SN/A INIT_PARAM(mmu, "Memory Controller"), 335360SN/A INIT_PARAM(addr, "Device Address") 336360SN/A 3371450SN/AEND_INIT_SIM_OBJECT_PARAMS(TsunamiPChip) 3383114Sgblack@eecs.umich.edu 339360SN/ACREATE_SIM_OBJECT(TsunamiPChip) 3406701Sgblack@eecs.umich.edu{ 3416701Sgblack@eecs.umich.edu return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu); 3426701Sgblack@eecs.umich.edu} 3436701Sgblack@eecs.umich.edu 344360SN/AREGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip) 345360SN/A