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 &section)
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