vtophys.cc revision 2107
17160Sgblack@eecs.umich.edu/*
27160Sgblack@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan
37160Sgblack@eecs.umich.edu * All rights reserved.
47160Sgblack@eecs.umich.edu *
57160Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67160Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77160Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87160Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97160Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107160Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117160Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127160Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137160Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147160Sgblack@eecs.umich.edu * this software without specific prior written permission.
157160Sgblack@eecs.umich.edu *
167160Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177160Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187160Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197160Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207160Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217160Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227160Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237160Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247160Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257160Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267160Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277160Sgblack@eecs.umich.edu */
287160Sgblack@eecs.umich.edu
297160Sgblack@eecs.umich.edu#include <string>
307160Sgblack@eecs.umich.edu
317160Sgblack@eecs.umich.edu#include "arch/alpha/vtophys.hh"
327160Sgblack@eecs.umich.edu#include "base/trace.hh"
337160Sgblack@eecs.umich.edu#include "cpu/exec_context.hh"
347160Sgblack@eecs.umich.edu#include "mem/functional/physical.hh"
357160Sgblack@eecs.umich.edu
367160Sgblack@eecs.umich.eduusing namespace std;
377160Sgblack@eecs.umich.eduusing namespace AlphaISA;
387160Sgblack@eecs.umich.edu
397160Sgblack@eecs.umich.eduAlphaISA::PageTableEntry
407160Sgblack@eecs.umich.edukernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr)
417160Sgblack@eecs.umich.edu{
427160Sgblack@eecs.umich.edu    Addr level1_pte = ptbr + vaddr.level1();
437160Sgblack@eecs.umich.edu    AlphaISA::PageTableEntry level1 = pmem->phys_read_qword(level1_pte);
447160Sgblack@eecs.umich.edu    if (!level1.valid()) {
457160Sgblack@eecs.umich.edu        DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr);
467160Sgblack@eecs.umich.edu        return 0;
478302SAli.Saidi@ARM.com    }
487160Sgblack@eecs.umich.edu
497160Sgblack@eecs.umich.edu    Addr level2_pte = level1.paddr() + vaddr.level2();
507160Sgblack@eecs.umich.edu    AlphaISA::PageTableEntry level2 = pmem->phys_read_qword(level2_pte);
517160Sgblack@eecs.umich.edu    if (!level2.valid()) {
527160Sgblack@eecs.umich.edu        DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr);
537160Sgblack@eecs.umich.edu        return 0;
547160Sgblack@eecs.umich.edu    }
558303SAli.Saidi@ARM.com
567160Sgblack@eecs.umich.edu    Addr level3_pte = level2.paddr() + vaddr.level3();
577160Sgblack@eecs.umich.edu    AlphaISA::PageTableEntry level3 = pmem->phys_read_qword(level3_pte);
587160Sgblack@eecs.umich.edu    if (!level3.valid()) {
597160Sgblack@eecs.umich.edu        DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr);
607160Sgblack@eecs.umich.edu        return 0;
617160Sgblack@eecs.umich.edu    }
627160Sgblack@eecs.umich.edu    return level3;
637160Sgblack@eecs.umich.edu}
647160Sgblack@eecs.umich.edu
657160Sgblack@eecs.umich.eduAddr
667160Sgblack@eecs.umich.eduvtophys(PhysicalMemory *xc, Addr vaddr)
677160Sgblack@eecs.umich.edu{
687160Sgblack@eecs.umich.edu    Addr paddr = 0;
697160Sgblack@eecs.umich.edu    if (AlphaISA::IsUSeg(vaddr))
707160Sgblack@eecs.umich.edu        DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
717160Sgblack@eecs.umich.edu    else if (AlphaISA::IsK0Seg(vaddr))
727160Sgblack@eecs.umich.edu        paddr = AlphaISA::K0Seg2Phys(vaddr);
737160Sgblack@eecs.umich.edu    else
747160Sgblack@eecs.umich.edu        panic("vtophys: ptbr is not set on virtual lookup");
757160Sgblack@eecs.umich.edu
767160Sgblack@eecs.umich.edu    DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
777160Sgblack@eecs.umich.edu
787160Sgblack@eecs.umich.edu    return paddr;
797160Sgblack@eecs.umich.edu}
807160Sgblack@eecs.umich.edu
817160Sgblack@eecs.umich.eduAddr
827160Sgblack@eecs.umich.eduvtophys(ExecContext *xc, Addr addr)
837160Sgblack@eecs.umich.edu{
847160Sgblack@eecs.umich.edu    AlphaISA::VAddr vaddr = addr;
857160Sgblack@eecs.umich.edu    Addr ptbr = xc->regs.ipr[AlphaISA::IPR_PALtemp20];
867162Sgblack@eecs.umich.edu    Addr paddr = 0;
877160Sgblack@eecs.umich.edu    //@todo Andrew couldn't remember why he commented some of this code
887160Sgblack@eecs.umich.edu    //so I put it back in. Perhaps something to do with gdb debugging?
897160Sgblack@eecs.umich.edu    if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) {
907160Sgblack@eecs.umich.edu        paddr = vaddr & ~ULL(1);
917760SGiacomo.Gabrielli@arm.com    } else {
927760SGiacomo.Gabrielli@arm.com        if (AlphaISA::IsK0Seg(vaddr)) {
937160Sgblack@eecs.umich.edu            paddr = AlphaISA::K0Seg2Phys(vaddr);
947160Sgblack@eecs.umich.edu        } else if (!ptbr) {
957160Sgblack@eecs.umich.edu            paddr = vaddr;
967760SGiacomo.Gabrielli@arm.com        } else {
977760SGiacomo.Gabrielli@arm.com            AlphaISA::PageTableEntry pte =
987160Sgblack@eecs.umich.edu                kernel_pte_lookup(xc->physmem, ptbr, vaddr);
997160Sgblack@eecs.umich.edu            if (pte.valid())
1007160Sgblack@eecs.umich.edu                paddr = pte.paddr() | vaddr.offset();
1017160Sgblack@eecs.umich.edu        }
1027160Sgblack@eecs.umich.edu    }
1037160Sgblack@eecs.umich.edu
1047160Sgblack@eecs.umich.edu
1057160Sgblack@eecs.umich.edu    DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
1067160Sgblack@eecs.umich.edu
1077160Sgblack@eecs.umich.edu    return paddr;
1087160Sgblack@eecs.umich.edu}
1097160Sgblack@eecs.umich.edu
1107160Sgblack@eecs.umich.eduuint8_t *
1117160Sgblack@eecs.umich.eduptomem(ExecContext *xc, Addr paddr, size_t len)
1127160Sgblack@eecs.umich.edu{
1137160Sgblack@eecs.umich.edu    return xc->physmem->dma_addr(paddr, len);
1147160Sgblack@eecs.umich.edu}
1157160Sgblack@eecs.umich.edu
1167160Sgblack@eecs.umich.eduuint8_t *
1177160Sgblack@eecs.umich.eduvtomem(ExecContext *xc, Addr vaddr, size_t len)
1187160Sgblack@eecs.umich.edu{
1197160Sgblack@eecs.umich.edu    Addr paddr = vtophys(xc, vaddr);
1207160Sgblack@eecs.umich.edu    return xc->physmem->dma_addr(paddr, len);
1217160Sgblack@eecs.umich.edu}
1227160Sgblack@eecs.umich.edu
1237160Sgblack@eecs.umich.eduvoid
1247160Sgblack@eecs.umich.eduCopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
1257160Sgblack@eecs.umich.edu{
1267160Sgblack@eecs.umich.edu    Addr paddr;
1277160Sgblack@eecs.umich.edu    char *dmaaddr;
1287160Sgblack@eecs.umich.edu    char *dst = (char *)dest;
1297160Sgblack@eecs.umich.edu    int len;
1307160Sgblack@eecs.umich.edu
1317160Sgblack@eecs.umich.edu    paddr = vtophys(xc, src);
1327160Sgblack@eecs.umich.edu    len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
1337160Sgblack@eecs.umich.edu              (int)cplen);
1347160Sgblack@eecs.umich.edu    dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
1357160Sgblack@eecs.umich.edu    assert(dmaaddr);
1367160Sgblack@eecs.umich.edu
1377160Sgblack@eecs.umich.edu    memcpy(dst, dmaaddr, len);
1387196Sgblack@eecs.umich.edu    if (len == cplen)
1397160Sgblack@eecs.umich.edu        return;
1407196Sgblack@eecs.umich.edu
1417196Sgblack@eecs.umich.edu    cplen -= len;
1427160Sgblack@eecs.umich.edu    dst += len;
1437160Sgblack@eecs.umich.edu    src += len;
1447160Sgblack@eecs.umich.edu
1457196Sgblack@eecs.umich.edu    while (cplen > AlphaISA::PageBytes) {
1467160Sgblack@eecs.umich.edu        paddr = vtophys(xc, src);
1477196Sgblack@eecs.umich.edu        dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
1487196Sgblack@eecs.umich.edu        assert(dmaaddr);
1497160Sgblack@eecs.umich.edu
1507160Sgblack@eecs.umich.edu        memcpy(dst, dmaaddr, AlphaISA::PageBytes);
1517160Sgblack@eecs.umich.edu        cplen -= AlphaISA::PageBytes;
1527196Sgblack@eecs.umich.edu        dst += AlphaISA::PageBytes;
1537160Sgblack@eecs.umich.edu        src += AlphaISA::PageBytes;
1547196Sgblack@eecs.umich.edu    }
1557196Sgblack@eecs.umich.edu
1567160Sgblack@eecs.umich.edu    if (cplen > 0) {
1577160Sgblack@eecs.umich.edu        paddr = vtophys(xc, src);
1587160Sgblack@eecs.umich.edu        dmaaddr = (char *)xc->physmem->dma_addr(paddr, cplen);
1597196Sgblack@eecs.umich.edu        assert(dmaaddr);
1607160Sgblack@eecs.umich.edu
1617196Sgblack@eecs.umich.edu        memcpy(dst, dmaaddr, cplen);
1627196Sgblack@eecs.umich.edu    }
1637160Sgblack@eecs.umich.edu}
1647160Sgblack@eecs.umich.edu
1657160Sgblack@eecs.umich.eduvoid
1667160Sgblack@eecs.umich.eduCopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
1677160Sgblack@eecs.umich.edu{
1687160Sgblack@eecs.umich.edu    Addr paddr;
1697160Sgblack@eecs.umich.edu    char *dmaaddr;
1707228Sgblack@eecs.umich.edu    char *src = (char *)source;
1717228Sgblack@eecs.umich.edu    int len;
1727160Sgblack@eecs.umich.edu
1737160Sgblack@eecs.umich.edu    paddr = vtophys(xc, dest);
1747160Sgblack@eecs.umich.edu    len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
1757160Sgblack@eecs.umich.edu              (int)cplen);
1767160Sgblack@eecs.umich.edu    dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
1777160Sgblack@eecs.umich.edu    assert(dmaaddr);
1787160Sgblack@eecs.umich.edu
1797228Sgblack@eecs.umich.edu    memcpy(dmaaddr, src, len);
1807228Sgblack@eecs.umich.edu    if (len == cplen)
1817160Sgblack@eecs.umich.edu        return;
1827160Sgblack@eecs.umich.edu
1837160Sgblack@eecs.umich.edu    cplen -= len;
1847160Sgblack@eecs.umich.edu    src += len;
1857160Sgblack@eecs.umich.edu    dest += len;
1867160Sgblack@eecs.umich.edu
1877160Sgblack@eecs.umich.edu    while (cplen > AlphaISA::PageBytes) {
1887160Sgblack@eecs.umich.edu        paddr = vtophys(xc, dest);
1897160Sgblack@eecs.umich.edu        dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
1907160Sgblack@eecs.umich.edu        assert(dmaaddr);
1917160Sgblack@eecs.umich.edu
1927160Sgblack@eecs.umich.edu        memcpy(dmaaddr, src, AlphaISA::PageBytes);
1937160Sgblack@eecs.umich.edu        cplen -= AlphaISA::PageBytes;
1947160Sgblack@eecs.umich.edu        src += AlphaISA::PageBytes;
1957160Sgblack@eecs.umich.edu        dest += AlphaISA::PageBytes;
1967160Sgblack@eecs.umich.edu    }
1977160Sgblack@eecs.umich.edu
1987160Sgblack@eecs.umich.edu    if (cplen > 0) {
1997160Sgblack@eecs.umich.edu        paddr = vtophys(xc, dest);
2007160Sgblack@eecs.umich.edu        dmaaddr = (char *)xc->physmem->dma_addr(paddr, cplen);
2017160Sgblack@eecs.umich.edu        assert(dmaaddr);
2027160Sgblack@eecs.umich.edu
2037160Sgblack@eecs.umich.edu        memcpy(dmaaddr, src, cplen);
2047160Sgblack@eecs.umich.edu    }
2057160Sgblack@eecs.umich.edu}
2067160Sgblack@eecs.umich.edu
2077160Sgblack@eecs.umich.eduvoid
2087160Sgblack@eecs.umich.eduCopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
2097160Sgblack@eecs.umich.edu{
2107160Sgblack@eecs.umich.edu    Addr paddr;
2117160Sgblack@eecs.umich.edu    char *dmaaddr;
2127160Sgblack@eecs.umich.edu    int len;
2137160Sgblack@eecs.umich.edu
2147160Sgblack@eecs.umich.edu    paddr = vtophys(xc, vaddr);
2157160Sgblack@eecs.umich.edu    len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
2167160Sgblack@eecs.umich.edu              (int)maxlen);
2177160Sgblack@eecs.umich.edu    dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
2187160Sgblack@eecs.umich.edu    assert(dmaaddr);
2197160Sgblack@eecs.umich.edu
2207160Sgblack@eecs.umich.edu    char *term = (char *)memchr(dmaaddr, 0, len);
2217160Sgblack@eecs.umich.edu    if (term)
2227160Sgblack@eecs.umich.edu        len = term - dmaaddr + 1;
2237160Sgblack@eecs.umich.edu
2247160Sgblack@eecs.umich.edu    memcpy(dst, dmaaddr, len);
2257160Sgblack@eecs.umich.edu
2267160Sgblack@eecs.umich.edu    if (term || len == maxlen)
2277160Sgblack@eecs.umich.edu        return;
2287160Sgblack@eecs.umich.edu
2297160Sgblack@eecs.umich.edu    maxlen -= len;
2307160Sgblack@eecs.umich.edu    dst += len;
2317160Sgblack@eecs.umich.edu    vaddr += len;
2327160Sgblack@eecs.umich.edu
2337160Sgblack@eecs.umich.edu    while (maxlen > AlphaISA::PageBytes) {
2347160Sgblack@eecs.umich.edu        paddr = vtophys(xc, vaddr);
2357160Sgblack@eecs.umich.edu        dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
2367160Sgblack@eecs.umich.edu        assert(dmaaddr);
2377160Sgblack@eecs.umich.edu
2387196Sgblack@eecs.umich.edu        char *term = (char *)memchr(dmaaddr, 0, AlphaISA::PageBytes);
2397196Sgblack@eecs.umich.edu        len = term ? (term - dmaaddr + 1) : AlphaISA::PageBytes;
2407196Sgblack@eecs.umich.edu
2417160Sgblack@eecs.umich.edu        memcpy(dst, dmaaddr, len);
2427160Sgblack@eecs.umich.edu        if (term)
2437160Sgblack@eecs.umich.edu            return;
2447160Sgblack@eecs.umich.edu
2457196Sgblack@eecs.umich.edu        maxlen -= AlphaISA::PageBytes;
2467196Sgblack@eecs.umich.edu        dst += AlphaISA::PageBytes;
2477196Sgblack@eecs.umich.edu        vaddr += AlphaISA::PageBytes;
2487160Sgblack@eecs.umich.edu    }
2497160Sgblack@eecs.umich.edu
2507160Sgblack@eecs.umich.edu    if (maxlen > 0) {
2517160Sgblack@eecs.umich.edu        paddr = vtophys(xc, vaddr);
2527160Sgblack@eecs.umich.edu        dmaaddr = (char *)xc->physmem->dma_addr(paddr, maxlen);
2537160Sgblack@eecs.umich.edu        assert(dmaaddr);
2547160Sgblack@eecs.umich.edu
2557228Sgblack@eecs.umich.edu        char *term = (char *)memchr(dmaaddr, 0, maxlen);
2567228Sgblack@eecs.umich.edu        len = term ? (term - dmaaddr + 1) : maxlen;
2577160Sgblack@eecs.umich.edu
2587160Sgblack@eecs.umich.edu        memcpy(dst, dmaaddr, len);
2597160Sgblack@eecs.umich.edu
2607160Sgblack@eecs.umich.edu        maxlen -= len;
2617160Sgblack@eecs.umich.edu    }
2627160Sgblack@eecs.umich.edu
2637160Sgblack@eecs.umich.edu    if (maxlen == 0)
2647228Sgblack@eecs.umich.edu        dst[maxlen] = '\0';
2657228Sgblack@eecs.umich.edu}
2667160Sgblack@eecs.umich.edu