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