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