1/*
2 * Copyright (c) 2016 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * For use for simulation and test purposes only
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Authors: Brandon Potter
34 */
35
36#ifndef __FD_ENTRY_HH__
37#define __FD_ENTRY_HH__
38
39#include <memory>
40#include <ostream>
41#include <string>
42
43#include "sim/serialize.hh"
44
45class EmulatedDriver;
46
47/**
48 * Holds a single file descriptor mapping and that mapping's data for
49 * processes running in syscall emulation mode.
50 */
51class FDEntry : public Serializable
52{
53  public:
54    FDEntry(bool close_on_exec = false)
55        : _closeOnExec(close_on_exec)
56    { }
57
58    virtual std::shared_ptr<FDEntry> clone() const = 0;
59
60    bool getCOE() const { return _closeOnExec; }
61
62    void setCOE(bool close_on_exec) { _closeOnExec = close_on_exec; }
63
64    virtual void serialize(CheckpointOut &cp) const;
65    virtual void unserialize(CheckpointIn &cp);
66
67  protected:
68    bool _closeOnExec;
69};
70
71/**
72 * Extends the base class to include a host-backed file descriptor field
73 * that records the integer used to represent the file descriptor on the host
74 * and the file's flags.
75 */
76class HBFDEntry: public FDEntry
77{
78  public:
79    HBFDEntry(int flags, int sim_fd, bool close_on_exec = false)
80        : FDEntry(close_on_exec), _flags(flags), _simFD(sim_fd)
81    { }
82
83    HBFDEntry(HBFDEntry const& reg, bool close_on_exec = false)
84        : FDEntry(close_on_exec), _flags(reg._flags), _simFD(reg._simFD)
85    { }
86
87    std::shared_ptr<FDEntry>
88    clone() const override
89    {
90        return std::make_shared<HBFDEntry>(*this);
91    }
92
93    int getFlags() const { return _flags; }
94    int getSimFD() const { return _simFD; }
95
96    void setFlags(int flags) { _flags = flags; }
97    void setSimFD(int sim_fd) { _simFD = sim_fd; }
98
99  protected:
100    int _flags;
101    int _simFD;
102};
103
104/**
105 * Holds file descriptors for host-backed files; host-backed files are
106 * files which were opened on the physical machine where the simulation
107 * is running (probably the thing on/under your desk). All regular files
108 * are redirected to make it appear that the file descriptor assignment
109 * starts at file descriptor '3' (not including stdin, stdout, stderr) and
110 * then grows upward.
111 */
112class FileFDEntry: public HBFDEntry
113{
114  public:
115    FileFDEntry(int sim_fd, int flags, std::string const& file_name,
116                uint64_t file_offset, bool close_on_exec = false)
117        : HBFDEntry(flags, sim_fd, close_on_exec),
118          _fileName(file_name), _fileOffset(file_offset)
119    { }
120
121    FileFDEntry(FileFDEntry const& reg, bool close_on_exec = false)
122        : HBFDEntry(reg._flags, reg._simFD, close_on_exec),
123          _fileName(reg._fileName), _fileOffset(reg._fileOffset)
124    { }
125
126    std::shared_ptr<FDEntry>
127    clone() const override
128    {
129        return std::make_shared<FileFDEntry>(*this);
130    }
131
132    std::string const& getFileName() const { return _fileName; }
133    uint64_t getFileOffset() const { return _fileOffset; }
134
135    void setFileName(std::string const& file_name) { _fileName = file_name; }
136    void setFileOffset(uint64_t f_off) { _fileOffset = f_off; }
137
138    void serialize(CheckpointOut &cp) const override;
139    void unserialize(CheckpointIn &cp) override;
140
141  private:
142    std::string _fileName;
143    uint64_t _fileOffset;
144};
145
146/**
147 * Holds the metadata needed to maintain the mappings for file descriptors
148 * allocated with the pipe() system calls and its variants.
149 */
150class PipeFDEntry: public HBFDEntry
151{
152  public:
153    enum EndType {
154        read = 0,
155        write = 1
156    };
157
158    PipeFDEntry(int sim_fd, int flags, EndType pipe_end_type,
159                bool close_on_exec = false)
160        : HBFDEntry(flags, sim_fd, close_on_exec), _pipeReadSource(-1),
161          _pipeEndType(pipe_end_type)
162    { }
163
164    PipeFDEntry(PipeFDEntry const& pipe, bool close_on_exec = false)
165        : HBFDEntry(pipe._flags, pipe._simFD, close_on_exec),
166          _pipeReadSource(pipe._pipeReadSource),
167          _pipeEndType(pipe._pipeEndType)
168    { }
169
170    std::shared_ptr<FDEntry>
171    clone() const override
172    {
173        return std::make_shared<PipeFDEntry>(*this);
174    }
175
176    EndType getEndType() const { return _pipeEndType; }
177    int getPipeReadSource() const { return _pipeReadSource; }
178
179    void setPipeReadSource(int tgt_fd) { _pipeReadSource = tgt_fd; }
180    void setEndType(EndType type) { _pipeEndType = type; }
181
182    void serialize(CheckpointOut &cp) const override;
183    void unserialize(CheckpointIn &cp) override;
184
185  private:
186    int _pipeReadSource;
187    EndType _pipeEndType;
188};
189
190/**
191 * Holds file descriptors needed to simulate devices opened with pseudo
192 * files (commonly with calls to ioctls).
193 */
194class DeviceFDEntry : public FDEntry
195{
196  public:
197    DeviceFDEntry(EmulatedDriver *driver, std::string const& file_name,
198                  bool close_on_exec = false)
199        : FDEntry(close_on_exec), _driver(driver), _fileName(file_name)
200    { }
201
202    DeviceFDEntry(DeviceFDEntry const& dev, bool close_on_exec = false)
203        : FDEntry(close_on_exec), _driver(dev._driver),
204          _fileName(dev._fileName)
205    { }
206
207    std::shared_ptr<FDEntry>
208    clone() const override
209    {
210        return std::make_shared<DeviceFDEntry>(*this);
211    }
212
213    EmulatedDriver *getDriver() const { return _driver; }
214    std::string const& getFileName() const { return _fileName; }
215
216    void serialize(CheckpointOut &cp) const override;
217    void unserialize(CheckpointIn &cp) override;
218
219  private:
220    EmulatedDriver *_driver;
221    std::string _fileName;
222};
223
224class SocketFDEntry: public HBFDEntry
225{
226  public:
227    SocketFDEntry(int sim_fd, int domain, int type, int protocol,
228                  bool close_on_exec = false)
229        : HBFDEntry(0, sim_fd, close_on_exec),
230          _domain(domain), _type(type), _protocol(protocol)
231    { }
232
233    SocketFDEntry(SocketFDEntry const& reg, bool close_on_exec = false)
234        : HBFDEntry(reg._flags, reg._simFD, close_on_exec),
235          _domain(reg._domain), _type(reg._type), _protocol(reg._protocol)
236    { }
237
238    std::shared_ptr<FDEntry>
239    clone() const override
240    {
241        return std::make_shared<SocketFDEntry>(*this);
242    }
243
244    int _domain;
245    int _type;
246    int _protocol;
247};
248
249#endif // __FD_ENTRY_HH__
250