vtophys.cc revision 547
114209Sandreas.sandberg@arm.com/*
211878Sandreas.sandberg@arm.com * Copyright (c) 2003 The Regents of The University of Michigan
311878Sandreas.sandberg@arm.com * All rights reserved.
411878Sandreas.sandberg@arm.com *
511878Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
611878Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
711878Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
811878Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
911878Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1011878Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
1111878Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
1211878Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
134126SN/A * contributors may be used to endorse or promote products derived from
148295Snate@binkert.org * this software without specific prior written permission.
154126SN/A *
164126SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
174126SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
184126SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
194126SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
204126SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
214126SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
224126SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
234126SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244126SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254126SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
264126SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274126SN/A */
284126SN/A
294126SN/A#include <string>
304126SN/A
314126SN/A#include "targetarch/pmap.h"
324126SN/A
334126SN/A#include "cpu/exec_context.hh"
344126SN/A#include "mem/functional_mem/physical_memory.hh"
354126SN/A#include "base/trace.hh"
364126SN/A#include "targetarch/vtophys.hh"
374126SN/A
384126SN/Ausing namespace std;
394126SN/A
404126SN/Ainline Addr
4111878Sandreas.sandberg@arm.comlevel3_index(Addr vaddr)
424126SN/A{ return (vaddr >> ALPHA_PGSHIFT) & PTEMASK; }
438296Snate@binkert.org
448296Snate@binkert.orginline Addr
4511802Sandreas.sandberg@arm.comlevel2_index(Addr vaddr)
468295Snate@binkert.org{ return (vaddr >> (ALPHA_PGSHIFT + NPTEPG_SHIFT)) & PTEMASK; }
478296Snate@binkert.org
484126SN/Ainline Addr
4911766Sandreas.sandberg@arm.comlevel1_index(Addr vaddr)
5011802Sandreas.sandberg@arm.com{ return (vaddr >> (ALPHA_PGSHIFT + 2 * NPTEPG_SHIFT)) & PTEMASK; }
5111802Sandreas.sandberg@arm.com
5211766Sandreas.sandberg@arm.comAddr
538296Snate@binkert.orgkernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, Addr vaddr)
5411878Sandreas.sandberg@arm.com{
5511878Sandreas.sandberg@arm.com    uint64_t level1_map = ptbr;
5611878Sandreas.sandberg@arm.com    Addr level1_pte = level1_map + (level1_index(vaddr) << PTESHIFT);
5711878Sandreas.sandberg@arm.com
5811878Sandreas.sandberg@arm.com    uint64_t level1 = pmem->phys_read_qword(level1_pte);
5911878Sandreas.sandberg@arm.com    if (!entry_valid(level1)) {
6011878Sandreas.sandberg@arm.com        DPRINTF(VtoPhys, "level 1 PTE not valid, va = %#\n", vaddr);
6111878Sandreas.sandberg@arm.com        return 0;
6211878Sandreas.sandberg@arm.com    }
6311878Sandreas.sandberg@arm.com
6411878Sandreas.sandberg@arm.com    uint64_t level2_map = PMAP_PTE_PA(level1);
6511878Sandreas.sandberg@arm.com    Addr level2_pte = level2_map + (level2_index(vaddr) << PTESHIFT);
6611878Sandreas.sandberg@arm.com    uint64_t level2 = pmem->phys_read_qword(level2_pte);
6711878Sandreas.sandberg@arm.com    if (!entry_valid(level2)) {
6811878Sandreas.sandberg@arm.com        DPRINTF(VtoPhys, "level 2 PTE not valid, va = %#x\n", vaddr);
6911878Sandreas.sandberg@arm.com        return 0;
7011878Sandreas.sandberg@arm.com    }
7111878Sandreas.sandberg@arm.com
7211878Sandreas.sandberg@arm.com    uint64_t level3_map = PMAP_PTE_PA(level2);
7311878Sandreas.sandberg@arm.com    Addr level3_pte = level3_map + (level3_index(vaddr) << PTESHIFT);
7413712Sandreas.sandberg@arm.com
7513712Sandreas.sandberg@arm.com    return level3_pte;
7613712Sandreas.sandberg@arm.com}
7713712Sandreas.sandberg@arm.com
7813712Sandreas.sandberg@arm.comAddr
7911878Sandreas.sandberg@arm.comvtophys(PhysicalMemory *xc, Addr vaddr)
8011878Sandreas.sandberg@arm.com{
8111878Sandreas.sandberg@arm.com    Addr paddr = 0;
8211878Sandreas.sandberg@arm.com    if (vaddr < ALPHA_K0SEG_BASE)
8311878Sandreas.sandberg@arm.com        DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
8411878Sandreas.sandberg@arm.com    else if (vaddr < ALPHA_K1SEG_BASE)
8511878Sandreas.sandberg@arm.com        paddr = ALPHA_K0SEG_TO_PHYS(vaddr);
8611878Sandreas.sandberg@arm.com    else
8711878Sandreas.sandberg@arm.com        panic("vtophys: ptbr is not set on virtual lookup");
8811878Sandreas.sandberg@arm.com
8911878Sandreas.sandberg@arm.com    DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
9011878Sandreas.sandberg@arm.com
9111878Sandreas.sandberg@arm.com    return paddr;
9211878Sandreas.sandberg@arm.com}
9311878Sandreas.sandberg@arm.com
9411878Sandreas.sandberg@arm.comAddr
9511878Sandreas.sandberg@arm.comvtophys(ExecContext *xc, Addr vaddr)
9611878Sandreas.sandberg@arm.com{
9711878Sandreas.sandberg@arm.com    Addr ptbr = xc->regs.ipr[AlphaISA::IPR_PALtemp20];
9811878Sandreas.sandberg@arm.com    Addr paddr = 0;
9911878Sandreas.sandberg@arm.com    if (PC_PAL(vaddr)) {
10011878Sandreas.sandberg@arm.com        paddr = vaddr & ~ULL(1);
10111878Sandreas.sandberg@arm.com    } else if (!ptbr) {
10211878Sandreas.sandberg@arm.com        paddr = vaddr;
10311878Sandreas.sandberg@arm.com    } else {
10411878Sandreas.sandberg@arm.com        if (vaddr >= ALPHA_K0SEG_BASE && vaddr <= ALPHA_K0SEG_END) {
10511878Sandreas.sandberg@arm.com            paddr = ALPHA_K0SEG_TO_PHYS(vaddr);
10611878Sandreas.sandberg@arm.com        } else {
10711878Sandreas.sandberg@arm.com            Addr pte = kernel_pte_lookup(xc->physmem, ptbr, vaddr);
10811878Sandreas.sandberg@arm.com            uint64_t entry = xc->physmem->phys_read_qword(pte);
10911878Sandreas.sandberg@arm.com            if (pte && entry_valid(entry))
11011878Sandreas.sandberg@arm.com                paddr = PMAP_PTE_PA(entry) | (vaddr & PGOFSET);
11111878Sandreas.sandberg@arm.com        }
11211878Sandreas.sandberg@arm.com    }
11311878Sandreas.sandberg@arm.com
11411878Sandreas.sandberg@arm.com    DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
11511878Sandreas.sandberg@arm.com
11611878Sandreas.sandberg@arm.com    return paddr;
11711878Sandreas.sandberg@arm.com}
11811878Sandreas.sandberg@arm.com
11911878Sandreas.sandberg@arm.comuint8_t *
12011878Sandreas.sandberg@arm.comptomem(ExecContext *xc, Addr paddr, size_t len)
12111878Sandreas.sandberg@arm.com{
12214209Sandreas.sandberg@arm.com    return xc->physmem->dma_addr(paddr, len);
12314209Sandreas.sandberg@arm.com}
12414209Sandreas.sandberg@arm.com
12514209Sandreas.sandberg@arm.comuint8_t *
12614209Sandreas.sandberg@arm.comvtomem(ExecContext *xc, Addr vaddr, size_t len)
12714209Sandreas.sandberg@arm.com{
12814209Sandreas.sandberg@arm.com    Addr paddr = vtophys(xc, vaddr);
12914209Sandreas.sandberg@arm.com    return xc->physmem->dma_addr(paddr, len);
13014209Sandreas.sandberg@arm.com}
13114209Sandreas.sandberg@arm.com
13214209Sandreas.sandberg@arm.comvoid
13314209Sandreas.sandberg@arm.comCopyData(ExecContext *xc, void *dest, Addr vaddr, size_t cplen)
13414209Sandreas.sandberg@arm.com{
13514209Sandreas.sandberg@arm.com    Addr paddr;
13614209Sandreas.sandberg@arm.com    char *dmaaddr;
13714209Sandreas.sandberg@arm.com    char *dst = (char *)dest;
13814209Sandreas.sandberg@arm.com    int len;
13914209Sandreas.sandberg@arm.com
14014209Sandreas.sandberg@arm.com    paddr = vtophys(xc, vaddr);
14114209Sandreas.sandberg@arm.com    len = min((int)(ALPHA_PGBYTES - (paddr & PGOFSET)), (int)cplen);
14214209Sandreas.sandberg@arm.com    dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
14314209Sandreas.sandberg@arm.com    assert(dmaaddr);
14414209Sandreas.sandberg@arm.com
14514209Sandreas.sandberg@arm.com    memcpy(dst, dmaaddr, len);
14614209Sandreas.sandberg@arm.com    if (len == cplen)
14714209Sandreas.sandberg@arm.com        return;
14814209Sandreas.sandberg@arm.com
14914209Sandreas.sandberg@arm.com    cplen -= len;
15014209Sandreas.sandberg@arm.com    dst += len;
15114209Sandreas.sandberg@arm.com    vaddr += len;
15214209Sandreas.sandberg@arm.com
15314209Sandreas.sandberg@arm.com    while (cplen > ALPHA_PGBYTES) {
15414209Sandreas.sandberg@arm.com        paddr = vtophys(xc, vaddr);
15514209Sandreas.sandberg@arm.com        dmaaddr = (char *)xc->physmem->dma_addr(paddr, ALPHA_PGBYTES);
15614209Sandreas.sandberg@arm.com        assert(dmaaddr);
15714209Sandreas.sandberg@arm.com
15814209Sandreas.sandberg@arm.com        memcpy(dst, dmaaddr, ALPHA_PGBYTES);
15914209Sandreas.sandberg@arm.com        cplen -= ALPHA_PGBYTES;
16014209Sandreas.sandberg@arm.com        dst += ALPHA_PGBYTES;
16111878Sandreas.sandberg@arm.com        vaddr += ALPHA_PGBYTES;
16211878Sandreas.sandberg@arm.com    }
16311878Sandreas.sandberg@arm.com
16411878Sandreas.sandberg@arm.com    if (cplen > 0) {
16511878Sandreas.sandberg@arm.com        paddr = vtophys(xc, vaddr);
16614209Sandreas.sandberg@arm.com        dmaaddr = (char *)xc->physmem->dma_addr(paddr, cplen);
16711878Sandreas.sandberg@arm.com        assert(dmaaddr);
16811878Sandreas.sandberg@arm.com
16914209Sandreas.sandberg@arm.com        memcpy(dst, dmaaddr, cplen);
17011878Sandreas.sandberg@arm.com    }
17111878Sandreas.sandberg@arm.com}
17211878Sandreas.sandberg@arm.com
17311878Sandreas.sandberg@arm.comvoid
17411878Sandreas.sandberg@arm.comCopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
17511878Sandreas.sandberg@arm.com{
17611878Sandreas.sandberg@arm.com    Addr paddr;
17711878Sandreas.sandberg@arm.com    char *dmaaddr;
17811878Sandreas.sandberg@arm.com    int len;
17911878Sandreas.sandberg@arm.com
18011878Sandreas.sandberg@arm.com    paddr = vtophys(xc, vaddr);
18111878Sandreas.sandberg@arm.com    len = min((int)(ALPHA_PGBYTES - (paddr & PGOFSET)), (int)maxlen);
18211878Sandreas.sandberg@arm.com    dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
18313712Sandreas.sandberg@arm.com    assert(dmaaddr);
18413712Sandreas.sandberg@arm.com
18513712Sandreas.sandberg@arm.com    char *term = (char *)memchr(dmaaddr, 0, len);
18613712Sandreas.sandberg@arm.com    if (term)
18713712Sandreas.sandberg@arm.com        len = term - dmaaddr + 1;
18811878Sandreas.sandberg@arm.com
18911878Sandreas.sandberg@arm.com    memcpy(dst, dmaaddr, len);
19011878Sandreas.sandberg@arm.com
19111878Sandreas.sandberg@arm.com    if (term || len == maxlen)
19211878Sandreas.sandberg@arm.com        return;
19311878Sandreas.sandberg@arm.com
19411878Sandreas.sandberg@arm.com    maxlen -= len;
19511878Sandreas.sandberg@arm.com    dst += len;
19611878Sandreas.sandberg@arm.com    vaddr += len;
1974126SN/A
1986001SN/A    while (maxlen > ALPHA_PGBYTES) {
19911802Sandreas.sandberg@arm.com        paddr = vtophys(xc, vaddr);
20011802Sandreas.sandberg@arm.com        dmaaddr = (char *)xc->physmem->dma_addr(paddr, ALPHA_PGBYTES);
2016001SN/A        assert(dmaaddr);
20214206Sandreas.sandberg@arm.com
20314206Sandreas.sandberg@arm.com        char *term = (char *)memchr(dmaaddr, 0, ALPHA_PGBYTES);
20414206Sandreas.sandberg@arm.com        len = term ? (term - dmaaddr + 1) : ALPHA_PGBYTES;
20514205Sandreas.sandberg@arm.com
20614205Sandreas.sandberg@arm.com        memcpy(dst, dmaaddr, len);
20714206Sandreas.sandberg@arm.com        if (term)
20814205Sandreas.sandberg@arm.com            return;
20914206Sandreas.sandberg@arm.com
21014205Sandreas.sandberg@arm.com        maxlen -= ALPHA_PGBYTES;
21114205Sandreas.sandberg@arm.com        dst += ALPHA_PGBYTES;
21214205Sandreas.sandberg@arm.com        vaddr += ALPHA_PGBYTES;
21314206Sandreas.sandberg@arm.com    }
21414205Sandreas.sandberg@arm.com
21514205Sandreas.sandberg@arm.com    if (maxlen > 0) {
21614205Sandreas.sandberg@arm.com        paddr = vtophys(xc, vaddr);
21714205Sandreas.sandberg@arm.com        dmaaddr = (char *)xc->physmem->dma_addr(paddr, maxlen);
21814205Sandreas.sandberg@arm.com        assert(dmaaddr);
21914205Sandreas.sandberg@arm.com
22014205Sandreas.sandberg@arm.com        char *term = (char *)memchr(dmaaddr, 0, maxlen);
22114205Sandreas.sandberg@arm.com        len = term ? (term - dmaaddr + 1) : maxlen;
22214205Sandreas.sandberg@arm.com
22314205Sandreas.sandberg@arm.com        memcpy(dst, dmaaddr, len);
22414205Sandreas.sandberg@arm.com
22514205Sandreas.sandberg@arm.com        maxlen -= len;
22614205Sandreas.sandberg@arm.com    }
2278295Snate@binkert.org
2288295Snate@binkert.org    if (maxlen == 0)
2298295Snate@binkert.org        dst[maxlen] = '\0';
2306001SN/A}
2318295Snate@binkert.org