18442Sgblack@eecs.umich.edu/* 28442Sgblack@eecs.umich.edu * Copyright (c) 2011 Google 311328Ssteve.reinhardt@amd.com * Copyright (c) 2015 Advanced Micro Devices, Inc. 48442Sgblack@eecs.umich.edu * All rights reserved. 58442Sgblack@eecs.umich.edu * 68442Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 78442Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 88442Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 98442Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 108442Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 118442Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 128442Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 138442Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 148442Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 158442Sgblack@eecs.umich.edu * this software without specific prior written permission. 168442Sgblack@eecs.umich.edu * 178442Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 188442Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 198442Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 208442Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 218442Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 228442Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 238442Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 248442Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 258442Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 268442Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 278442Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 288442Sgblack@eecs.umich.edu * 298442Sgblack@eecs.umich.edu * Authors: Gabe Black 308442Sgblack@eecs.umich.edu */ 318442Sgblack@eecs.umich.edu 328442Sgblack@eecs.umich.edu#ifndef __ARCH_X86_MEMHELPERS_HH__ 338442Sgblack@eecs.umich.edu#define __ARCH_X86_MEMHELPERS_HH__ 348442Sgblack@eecs.umich.edu 3511328Ssteve.reinhardt@amd.com#include <array> 3611328Ssteve.reinhardt@amd.com 378442Sgblack@eecs.umich.edu#include "base/types.hh" 3812234Sgabeblack@google.com#include "cpu/exec_context.hh" 398442Sgblack@eecs.umich.edu#include "sim/byteswap.hh" 408442Sgblack@eecs.umich.edu#include "sim/insttracer.hh" 418442Sgblack@eecs.umich.edu 428442Sgblack@eecs.umich.edunamespace X86ISA 438442Sgblack@eecs.umich.edu{ 448442Sgblack@eecs.umich.edu 4511303Ssteve.reinhardt@amd.com/// Initiate a read from memory in timing mode. 4612234Sgabeblack@google.comstatic Fault 4712234Sgabeblack@google.cominitiateMemRead(ExecContext *xc, Trace::InstRecord *traceData, Addr addr, 4811608Snikos.nikoleris@arm.com unsigned dataSize, Request::Flags flags) 498442Sgblack@eecs.umich.edu{ 5011303Ssteve.reinhardt@amd.com return xc->initiateMemRead(addr, dataSize, flags); 518442Sgblack@eecs.umich.edu} 528442Sgblack@eecs.umich.edu 5311328Ssteve.reinhardt@amd.comstatic void 5411328Ssteve.reinhardt@amd.comgetMem(PacketPtr pkt, uint64_t &mem, unsigned dataSize, 5511328Ssteve.reinhardt@amd.com Trace::InstRecord *traceData) 568442Sgblack@eecs.umich.edu{ 578442Sgblack@eecs.umich.edu switch (dataSize) { 588442Sgblack@eecs.umich.edu case 1: 5913229Sgabeblack@google.com mem = pkt->getLE<uint8_t>(); 608442Sgblack@eecs.umich.edu break; 618442Sgblack@eecs.umich.edu case 2: 6213229Sgabeblack@google.com mem = pkt->getLE<uint16_t>(); 638442Sgblack@eecs.umich.edu break; 648442Sgblack@eecs.umich.edu case 4: 6513229Sgabeblack@google.com mem = pkt->getLE<uint32_t>(); 668442Sgblack@eecs.umich.edu break; 678442Sgblack@eecs.umich.edu case 8: 6813229Sgabeblack@google.com mem = pkt->getLE<uint64_t>(); 698442Sgblack@eecs.umich.edu break; 708442Sgblack@eecs.umich.edu default: 718442Sgblack@eecs.umich.edu panic("Unhandled size in getMem.\n"); 728442Sgblack@eecs.umich.edu } 738442Sgblack@eecs.umich.edu if (traceData) 748442Sgblack@eecs.umich.edu traceData->setData(mem); 758442Sgblack@eecs.umich.edu} 768442Sgblack@eecs.umich.edu 7712384Sgabeblack@google.comtemplate <typename T, size_t N> 7812384Sgabeblack@google.comstatic void 7912384Sgabeblack@google.comgetPackedMem(PacketPtr pkt, std::array<uint64_t, N> &mem, unsigned dataSize) 8012384Sgabeblack@google.com{ 8113229Sgabeblack@google.com std::array<T, N> real_mem = pkt->getLE<std::array<T, N> >(); 8212384Sgabeblack@google.com for (int i = 0; i < N; i++) 8312384Sgabeblack@google.com mem[i] = real_mem[i]; 8412384Sgabeblack@google.com} 8511328Ssteve.reinhardt@amd.com 8611328Ssteve.reinhardt@amd.comtemplate <size_t N> 8712384Sgabeblack@google.comstatic void 8811328Ssteve.reinhardt@amd.comgetMem(PacketPtr pkt, std::array<uint64_t, N> &mem, unsigned dataSize, 8911328Ssteve.reinhardt@amd.com Trace::InstRecord *traceData) 9011328Ssteve.reinhardt@amd.com{ 9112384Sgabeblack@google.com switch (dataSize) { 9212384Sgabeblack@google.com case 4: 9312384Sgabeblack@google.com getPackedMem<uint32_t, N>(pkt, mem, dataSize); 9412384Sgabeblack@google.com break; 9512384Sgabeblack@google.com case 8: 9612384Sgabeblack@google.com getPackedMem<uint64_t, N>(pkt, mem, dataSize); 9712384Sgabeblack@google.com break; 9812384Sgabeblack@google.com default: 9912384Sgabeblack@google.com panic("Unhandled element size in getMem.\n"); 10012384Sgabeblack@google.com } 10111328Ssteve.reinhardt@amd.com if (traceData) 10211328Ssteve.reinhardt@amd.com traceData->setData(mem[0]); 10311328Ssteve.reinhardt@amd.com} 10411328Ssteve.reinhardt@amd.com 10511328Ssteve.reinhardt@amd.com 10612234Sgabeblack@google.comstatic Fault 10712234Sgabeblack@google.comreadMemAtomic(ExecContext *xc, Trace::InstRecord *traceData, Addr addr, 10812234Sgabeblack@google.com uint64_t &mem, unsigned dataSize, Request::Flags flags) 1098442Sgblack@eecs.umich.edu{ 1108442Sgblack@eecs.umich.edu memset(&mem, 0, sizeof(mem)); 11111301Ssteve.reinhardt@amd.com Fault fault = xc->readMem(addr, (uint8_t *)&mem, dataSize, flags); 1128442Sgblack@eecs.umich.edu if (fault == NoFault) { 1138442Sgblack@eecs.umich.edu // If LE to LE, this is a nop, if LE to BE, the actual data ends up 1148442Sgblack@eecs.umich.edu // in the right place because the LSBs where at the low addresses on 1158442Sgblack@eecs.umich.edu // access. This doesn't work for BE guests. 1168442Sgblack@eecs.umich.edu mem = gtoh(mem); 1178442Sgblack@eecs.umich.edu if (traceData) 1188442Sgblack@eecs.umich.edu traceData->setData(mem); 1198442Sgblack@eecs.umich.edu } 1208442Sgblack@eecs.umich.edu return fault; 1218442Sgblack@eecs.umich.edu} 1228442Sgblack@eecs.umich.edu 12312384Sgabeblack@google.comtemplate <typename T, size_t N> 12412384Sgabeblack@google.comstatic Fault 12512384Sgabeblack@google.comreadPackedMemAtomic(ExecContext *xc, Addr addr, std::array<uint64_t, N> &mem, 12612384Sgabeblack@google.com unsigned flags) 12712384Sgabeblack@google.com{ 12812384Sgabeblack@google.com std::array<T, N> real_mem; 12912384Sgabeblack@google.com Fault fault = xc->readMem(addr, (uint8_t *)&real_mem, 13012384Sgabeblack@google.com sizeof(T) * N, flags); 13112384Sgabeblack@google.com if (fault == NoFault) { 13212384Sgabeblack@google.com real_mem = gtoh(real_mem); 13312384Sgabeblack@google.com for (int i = 0; i < N; i++) 13412384Sgabeblack@google.com mem[i] = real_mem[i]; 13512384Sgabeblack@google.com } 13612384Sgabeblack@google.com return fault; 13712384Sgabeblack@google.com} 13812384Sgabeblack@google.com 13912234Sgabeblack@google.comtemplate <size_t N> 14012384Sgabeblack@google.comstatic Fault 14112234Sgabeblack@google.comreadMemAtomic(ExecContext *xc, Trace::InstRecord *traceData, Addr addr, 14211328Ssteve.reinhardt@amd.com std::array<uint64_t, N> &mem, unsigned dataSize, 14311328Ssteve.reinhardt@amd.com unsigned flags) 14411328Ssteve.reinhardt@amd.com{ 14512384Sgabeblack@google.com Fault fault = NoFault; 14611328Ssteve.reinhardt@amd.com 14712384Sgabeblack@google.com switch (dataSize) { 14812384Sgabeblack@google.com case 4: 14912384Sgabeblack@google.com fault = readPackedMemAtomic<uint32_t, N>(xc, addr, mem, flags); 15012384Sgabeblack@google.com break; 15112384Sgabeblack@google.com case 8: 15212384Sgabeblack@google.com fault = readPackedMemAtomic<uint64_t, N>(xc, addr, mem, flags); 15312384Sgabeblack@google.com break; 15412384Sgabeblack@google.com default: 15512384Sgabeblack@google.com panic("Unhandled element size in readMemAtomic\n"); 15612384Sgabeblack@google.com } 15712384Sgabeblack@google.com if (fault == NoFault && traceData) 15812384Sgabeblack@google.com traceData->setData(mem[0]); 15912384Sgabeblack@google.com return fault; 16012384Sgabeblack@google.com} 16111328Ssteve.reinhardt@amd.com 16212384Sgabeblack@google.comtemplate <typename T, size_t N> 16312384Sgabeblack@google.comstatic Fault 16412384Sgabeblack@google.comwritePackedMem(ExecContext *xc, std::array<uint64_t, N> &mem, Addr addr, 16512384Sgabeblack@google.com unsigned flags, uint64_t *res) 16612384Sgabeblack@google.com{ 16712384Sgabeblack@google.com std::array<T, N> real_mem; 16812384Sgabeblack@google.com for (int i = 0; i < N; i++) 16912384Sgabeblack@google.com real_mem[i] = mem[i]; 17012384Sgabeblack@google.com real_mem = htog(real_mem); 17112384Sgabeblack@google.com return xc->writeMem((uint8_t *)&real_mem, sizeof(T) * N, 17212384Sgabeblack@google.com addr, flags, res); 17311328Ssteve.reinhardt@amd.com} 17411328Ssteve.reinhardt@amd.com 17512234Sgabeblack@google.comstatic Fault 17612234Sgabeblack@google.comwriteMemTiming(ExecContext *xc, Trace::InstRecord *traceData, uint64_t mem, 17711608Snikos.nikoleris@arm.com unsigned dataSize, Addr addr, Request::Flags flags, 17811608Snikos.nikoleris@arm.com uint64_t *res) 1798442Sgblack@eecs.umich.edu{ 18012384Sgabeblack@google.com if (traceData) 1818442Sgblack@eecs.umich.edu traceData->setData(mem); 18213914Sgabeblack@google.com mem = htog(mem); 1838444Sgblack@eecs.umich.edu return xc->writeMem((uint8_t *)&mem, dataSize, addr, flags, res); 1848442Sgblack@eecs.umich.edu} 1858442Sgblack@eecs.umich.edu 18612234Sgabeblack@google.comtemplate <size_t N> 18712384Sgabeblack@google.comstatic Fault 18812234Sgabeblack@google.comwriteMemTiming(ExecContext *xc, Trace::InstRecord *traceData, 18911328Ssteve.reinhardt@amd.com std::array<uint64_t, N> &mem, unsigned dataSize, 19011328Ssteve.reinhardt@amd.com Addr addr, unsigned flags, uint64_t *res) 19111328Ssteve.reinhardt@amd.com{ 19212384Sgabeblack@google.com if (traceData) 19312384Sgabeblack@google.com traceData->setData(mem[0]); 19411328Ssteve.reinhardt@amd.com 19512384Sgabeblack@google.com switch (dataSize) { 19612384Sgabeblack@google.com case 4: 19712384Sgabeblack@google.com return writePackedMem<uint32_t, N>(xc, mem, addr, flags, res); 19812384Sgabeblack@google.com case 8: 19912384Sgabeblack@google.com return writePackedMem<uint64_t, N>(xc, mem, addr, flags, res); 20012384Sgabeblack@google.com default: 20112384Sgabeblack@google.com panic("Unhandled element size in writeMemTiming.\n"); 20211328Ssteve.reinhardt@amd.com } 20311328Ssteve.reinhardt@amd.com} 20411328Ssteve.reinhardt@amd.com 20512234Sgabeblack@google.comstatic Fault 20612234Sgabeblack@google.comwriteMemAtomic(ExecContext *xc, Trace::InstRecord *traceData, uint64_t mem, 20711608Snikos.nikoleris@arm.com unsigned dataSize, Addr addr, Request::Flags flags, 20811608Snikos.nikoleris@arm.com uint64_t *res) 2098442Sgblack@eecs.umich.edu{ 21012384Sgabeblack@google.com if (traceData) 21111301Ssteve.reinhardt@amd.com traceData->setData(mem); 21213914Sgabeblack@google.com uint64_t host_mem = htog(mem); 21311301Ssteve.reinhardt@amd.com Fault fault = 21411301Ssteve.reinhardt@amd.com xc->writeMem((uint8_t *)&host_mem, dataSize, addr, flags, res); 21512384Sgabeblack@google.com if (fault == NoFault && res) 2168442Sgblack@eecs.umich.edu *res = gtoh(*res); 2178442Sgblack@eecs.umich.edu return fault; 2188442Sgblack@eecs.umich.edu} 2198442Sgblack@eecs.umich.edu 22012234Sgabeblack@google.comtemplate <size_t N> 22112384Sgabeblack@google.comstatic Fault 22212234Sgabeblack@google.comwriteMemAtomic(ExecContext *xc, Trace::InstRecord *traceData, 22311328Ssteve.reinhardt@amd.com std::array<uint64_t, N> &mem, unsigned dataSize, 22411328Ssteve.reinhardt@amd.com Addr addr, unsigned flags, uint64_t *res) 22511328Ssteve.reinhardt@amd.com{ 22612384Sgabeblack@google.com if (traceData) 22711328Ssteve.reinhardt@amd.com traceData->setData(mem[0]); 22812384Sgabeblack@google.com 22912384Sgabeblack@google.com Fault fault; 23012384Sgabeblack@google.com switch (dataSize) { 23112384Sgabeblack@google.com case 4: 23212384Sgabeblack@google.com fault = writePackedMem<uint32_t, N>(xc, mem, addr, flags, res); 23312384Sgabeblack@google.com break; 23412384Sgabeblack@google.com case 8: 23512384Sgabeblack@google.com fault = writePackedMem<uint64_t, N>(xc, mem, addr, flags, res); 23612384Sgabeblack@google.com break; 23712384Sgabeblack@google.com default: 23812384Sgabeblack@google.com panic("Unhandled element size in writeMemAtomic.\n"); 23911328Ssteve.reinhardt@amd.com } 24011328Ssteve.reinhardt@amd.com 24112384Sgabeblack@google.com if (fault == NoFault && res) 24211328Ssteve.reinhardt@amd.com *res = gtoh(*res); 24311328Ssteve.reinhardt@amd.com 24411328Ssteve.reinhardt@amd.com return fault; 24511328Ssteve.reinhardt@amd.com} 24611328Ssteve.reinhardt@amd.com 2478442Sgblack@eecs.umich.edu} 2488442Sgblack@eecs.umich.edu 2498442Sgblack@eecs.umich.edu#endif 250