110497Ssteve.reinhardt@amd.com/*
210497Ssteve.reinhardt@amd.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
310497Ssteve.reinhardt@amd.com * All rights reserved.
410497Ssteve.reinhardt@amd.com *
510497Ssteve.reinhardt@amd.com * Redistribution and use in source and binary forms, with or without
610497Ssteve.reinhardt@amd.com * modification, are permitted provided that the following conditions are
710497Ssteve.reinhardt@amd.com * met: redistributions of source code must retain the above copyright
810497Ssteve.reinhardt@amd.com * notice, this list of conditions and the following disclaimer;
910497Ssteve.reinhardt@amd.com * redistributions in binary form must reproduce the above copyright
1010497Ssteve.reinhardt@amd.com * notice, this list of conditions and the following disclaimer in the
1110497Ssteve.reinhardt@amd.com * documentation and/or other materials provided with the distribution;
1210497Ssteve.reinhardt@amd.com * neither the name of the copyright holders nor the names of its
1310497Ssteve.reinhardt@amd.com * contributors may be used to endorse or promote products derived from
1410497Ssteve.reinhardt@amd.com * this software without specific prior written permission.
1510497Ssteve.reinhardt@amd.com *
1610497Ssteve.reinhardt@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710497Ssteve.reinhardt@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810497Ssteve.reinhardt@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910497Ssteve.reinhardt@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010497Ssteve.reinhardt@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110497Ssteve.reinhardt@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210497Ssteve.reinhardt@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310497Ssteve.reinhardt@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410497Ssteve.reinhardt@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510497Ssteve.reinhardt@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610497Ssteve.reinhardt@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710497Ssteve.reinhardt@amd.com *
2810497Ssteve.reinhardt@amd.com * Authors: Steve Reinhardt
2910497Ssteve.reinhardt@amd.com */
3010497Ssteve.reinhardt@amd.com
3110497Ssteve.reinhardt@amd.com#ifndef __SIM_SYSCALL_EMUL_BUF_HH__
3210497Ssteve.reinhardt@amd.com#define __SIM_SYSCALL_EMUL_BUF_HH__
3310497Ssteve.reinhardt@amd.com
3410497Ssteve.reinhardt@amd.com///
3510497Ssteve.reinhardt@amd.com/// @file syscall_emul_buf.hh
3610497Ssteve.reinhardt@amd.com///
3710497Ssteve.reinhardt@amd.com/// This file defines buffer classes used to handle pointer arguments
3810497Ssteve.reinhardt@amd.com/// in emulated syscalls.
3910497Ssteve.reinhardt@amd.com
4010497Ssteve.reinhardt@amd.com#include <cstring>
4110497Ssteve.reinhardt@amd.com
4210497Ssteve.reinhardt@amd.com#include "base/types.hh"
4310497Ssteve.reinhardt@amd.com#include "mem/se_translating_port_proxy.hh"
4410497Ssteve.reinhardt@amd.com
4510497Ssteve.reinhardt@amd.com/**
4610497Ssteve.reinhardt@amd.com * Base class for BufferArg and TypedBufferArg, Not intended to be
4710497Ssteve.reinhardt@amd.com * used directly.
4810497Ssteve.reinhardt@amd.com *
4910497Ssteve.reinhardt@amd.com * The BufferArg classes represent buffers in target user space that
5010497Ssteve.reinhardt@amd.com * are passed by reference to an (emulated) system call.  Each
5110497Ssteve.reinhardt@amd.com * instance provides an internal (simulator-space) buffer of the
5210497Ssteve.reinhardt@amd.com * appropriate size and tracks the user-space address.  The copyIn()
5310497Ssteve.reinhardt@amd.com * and copyOut() methods copy the user-space buffer to and from the
5410497Ssteve.reinhardt@amd.com * simulator-space buffer, respectively.
5510497Ssteve.reinhardt@amd.com */
5610497Ssteve.reinhardt@amd.comclass BaseBufferArg {
5710497Ssteve.reinhardt@amd.com
5810497Ssteve.reinhardt@amd.com  public:
5910497Ssteve.reinhardt@amd.com
6010497Ssteve.reinhardt@amd.com    /**
6110497Ssteve.reinhardt@amd.com     * Allocate a buffer of size 'size' representing the memory at
6210497Ssteve.reinhardt@amd.com     * target address 'addr'.
6310497Ssteve.reinhardt@amd.com     */
6410497Ssteve.reinhardt@amd.com    BaseBufferArg(Addr _addr, int _size)
6510497Ssteve.reinhardt@amd.com        : addr(_addr), size(_size), bufPtr(new uint8_t[size])
6610497Ssteve.reinhardt@amd.com    {
6710497Ssteve.reinhardt@amd.com        // clear out buffer: in case we only partially populate this,
6810497Ssteve.reinhardt@amd.com        // and then do a copyOut(), we want to make sure we don't
6910497Ssteve.reinhardt@amd.com        // introduce any random junk into the simulated address space
7010497Ssteve.reinhardt@amd.com        memset(bufPtr, 0, size);
7110497Ssteve.reinhardt@amd.com    }
7210497Ssteve.reinhardt@amd.com
7310498Ssteve.reinhardt@amd.com    ~BaseBufferArg() { delete [] bufPtr; }
7410497Ssteve.reinhardt@amd.com
7510497Ssteve.reinhardt@amd.com    /**
7610497Ssteve.reinhardt@amd.com     * copy data into simulator space (read from target memory)
7710497Ssteve.reinhardt@amd.com     */
7814020Sgabeblack@google.com    bool
7914020Sgabeblack@google.com    copyIn(PortProxy &memproxy)
8010497Ssteve.reinhardt@amd.com    {
8110497Ssteve.reinhardt@amd.com        memproxy.readBlob(addr, bufPtr, size);
8210497Ssteve.reinhardt@amd.com        return true;    // no EFAULT detection for now
8310497Ssteve.reinhardt@amd.com    }
8410497Ssteve.reinhardt@amd.com
8510497Ssteve.reinhardt@amd.com    /**
8610497Ssteve.reinhardt@amd.com     * copy data out of simulator space (write to target memory)
8710497Ssteve.reinhardt@amd.com     */
8814020Sgabeblack@google.com    bool
8914020Sgabeblack@google.com    copyOut(PortProxy &memproxy)
9010497Ssteve.reinhardt@amd.com    {
9110497Ssteve.reinhardt@amd.com        memproxy.writeBlob(addr, bufPtr, size);
9210497Ssteve.reinhardt@amd.com        return true;    // no EFAULT detection for now
9310497Ssteve.reinhardt@amd.com    }
9410497Ssteve.reinhardt@amd.com
9510497Ssteve.reinhardt@amd.com  protected:
9610497Ssteve.reinhardt@amd.com    const Addr addr;        ///< address of buffer in target address space
9710497Ssteve.reinhardt@amd.com    const int size;         ///< buffer size
9810497Ssteve.reinhardt@amd.com    uint8_t * const bufPtr; ///< pointer to buffer in simulator space
9910497Ssteve.reinhardt@amd.com};
10010497Ssteve.reinhardt@amd.com
10110497Ssteve.reinhardt@amd.com/**
10210497Ssteve.reinhardt@amd.com * BufferArg represents an untyped buffer in target user space that is
10310497Ssteve.reinhardt@amd.com * passed by reference to an (emulated) system call.
10410497Ssteve.reinhardt@amd.com */
10510497Ssteve.reinhardt@amd.comclass BufferArg : public BaseBufferArg
10610497Ssteve.reinhardt@amd.com{
10710497Ssteve.reinhardt@amd.com  public:
10810497Ssteve.reinhardt@amd.com    /**
10910497Ssteve.reinhardt@amd.com     * Allocate a buffer of size 'size' representing the memory at
11010497Ssteve.reinhardt@amd.com     * target address 'addr'.
11110497Ssteve.reinhardt@amd.com     */
11210497Ssteve.reinhardt@amd.com    BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
11310497Ssteve.reinhardt@amd.com
11410497Ssteve.reinhardt@amd.com    /**
11510497Ssteve.reinhardt@amd.com     * Return a pointer to the internal simulator-space buffer.
11610497Ssteve.reinhardt@amd.com     */
11710497Ssteve.reinhardt@amd.com    void *bufferPtr() { return bufPtr; }
11810497Ssteve.reinhardt@amd.com};
11910497Ssteve.reinhardt@amd.com
12010497Ssteve.reinhardt@amd.com/**
12110497Ssteve.reinhardt@amd.com * TypedBufferArg is a class template; instances of this template
12210497Ssteve.reinhardt@amd.com * represent typed buffers in target user space that are passed by
12310497Ssteve.reinhardt@amd.com * reference to an (emulated) system call.
12410497Ssteve.reinhardt@amd.com *
12510497Ssteve.reinhardt@amd.com * This template provides operator overloads for convenience, allowing
12610497Ssteve.reinhardt@amd.com * for example the use of '->' to reference fields within a struct
12710497Ssteve.reinhardt@amd.com * type.
12810497Ssteve.reinhardt@amd.com */
12910497Ssteve.reinhardt@amd.comtemplate <class T>
13010497Ssteve.reinhardt@amd.comclass TypedBufferArg : public BaseBufferArg
13110497Ssteve.reinhardt@amd.com{
13210497Ssteve.reinhardt@amd.com  public:
13310497Ssteve.reinhardt@amd.com    /**
13410497Ssteve.reinhardt@amd.com     * Allocate a buffer of type T representing the memory at target
13510497Ssteve.reinhardt@amd.com     * address 'addr'. The user can optionally specify a specific
13610497Ssteve.reinhardt@amd.com     * number of bytes to allocate to deal with structs that have
13710497Ssteve.reinhardt@amd.com     * variable-size arrays at the end.
13810497Ssteve.reinhardt@amd.com     */
13910497Ssteve.reinhardt@amd.com    TypedBufferArg(Addr _addr, int _size = sizeof(T))
14010497Ssteve.reinhardt@amd.com        : BaseBufferArg(_addr, _size)
14110497Ssteve.reinhardt@amd.com    { }
14210497Ssteve.reinhardt@amd.com
14310497Ssteve.reinhardt@amd.com    /**
14410497Ssteve.reinhardt@amd.com     * Convert TypedBufferArg<T> to a pointer to T that points to the
14510497Ssteve.reinhardt@amd.com     * internal buffer.
14610497Ssteve.reinhardt@amd.com     */
14710497Ssteve.reinhardt@amd.com    operator T*() { return (T *)bufPtr; }
14810497Ssteve.reinhardt@amd.com
14910497Ssteve.reinhardt@amd.com    /**
15010497Ssteve.reinhardt@amd.com     * Convert TypedBufferArg<T> to a reference to T that references the
15110497Ssteve.reinhardt@amd.com     * internal buffer value.
15210497Ssteve.reinhardt@amd.com     */
15310497Ssteve.reinhardt@amd.com    T &operator*()       { return *((T *)bufPtr); }
15410497Ssteve.reinhardt@amd.com
15510497Ssteve.reinhardt@amd.com
15610497Ssteve.reinhardt@amd.com    /**
15710497Ssteve.reinhardt@amd.com     * Enable the use of '->' to reference fields where T is a struct
15810497Ssteve.reinhardt@amd.com     * type.
15910497Ssteve.reinhardt@amd.com     */
16010497Ssteve.reinhardt@amd.com    T* operator->()      { return (T *)bufPtr; }
16110497Ssteve.reinhardt@amd.com
16210497Ssteve.reinhardt@amd.com    /**
16310497Ssteve.reinhardt@amd.com     * Enable the use of '[]' to reference fields where T is an array
16410497Ssteve.reinhardt@amd.com     * type.
16510497Ssteve.reinhardt@amd.com     */
16610497Ssteve.reinhardt@amd.com    T &operator[](int i) { return ((T *)bufPtr)[i]; }
16710497Ssteve.reinhardt@amd.com};
16810497Ssteve.reinhardt@amd.com
16910497Ssteve.reinhardt@amd.com
17010497Ssteve.reinhardt@amd.com#endif // __SIM_SYSCALL_EMUL_BUF_HH__
171