Go to the documentation of this file.
42 #include <netinet/in.h>
43 #include <sys/socket.h>
44 #include <sys/types.h>
54 #include "debug/VIO9P.hh"
55 #include "debug/VIO9PData.hh"
56 #include "params/VirtIO9PBase.hh"
57 #include "params/VirtIO9PDiod.hh"
58 #include "params/VirtIO9PProxy.hh"
59 #include "params/VirtIO9PSocket.hh"
72 #define P9MSG(type, name) \
73 { (type), P9MsgInfo((type), "T" # name ) }, \
74 { (type + 1), P9MsgInfo((type + 1), "R" # name ) }
88 P9MSG(32, XATTRCREATE),
117 sizeof(
Config) + params->tag.size(),
143 DPRINTF(VIO9P,
"Got input data descriptor (len: %i)\n", desc->
size());
166 DPRINTF(VIO9P,
"Sending RMsg\n");
177 out_desc = out_desc->
next();
179 panic(
"sendRMsg: Framing error, no output descriptor.\n");
184 out_desc->
chainWrite(0, (uint8_t *)&header_out,
sizeof(header_out));
201 DPRINTF(VIO9P,
"P9Msg[len = %i, type = %s (%i), tag = %i]\n",
204 DPRINTF(VIO9P,
"P9Msg[len = %i, type = Unknown (%i), tag = %i]\n",
226 warn(
"Serializing VirtIO9Base device after device has been used. It is "
227 "likely that state will be lost, and that the device will cease "
241 warn(
"Unserializing VirtIO9Base device after device has been used. It is "
242 "likely that state has been lost, and that the device will cease "
251 const uint8_t *
data,
size_t size)
259 memcpy(out, (uint8_t *)&header_out,
sizeof(header_out));
260 memcpy(out +
sizeof(header_out),
data, size);
261 writeAll(out,
sizeof(header_out) + size);
273 panic(
"Payload length is negative!\n");
274 uint8_t
data[payload_len];
289 panic(
"readAll: Read failed: %i\n", -ret);
304 panic(
"writeAll: write failed: %i\n", -ret);
315 fd_to_diod(-1), fd_from_diod(-1), diod_pid(-1)
339 const int DIOD_RFD = 3;
340 const int DIOD_WFD = 4;
342 const char *diod(
p->diod.c_str());
344 DPRINTF(VIO9P,
"Using diod at %s \n",
p->diod.c_str());
346 if (pipe(pipe_rfd) == -1 || pipe(pipe_wfd) == -1)
347 panic(
"Failed to create DIOD pipes: %i\n", errno);
353 int socket_id = socket(AF_UNIX, SOCK_STREAM, 0);
354 if (socket_id == -1) {
355 panic(
"Socket creation failed %i \n", errno);
358 struct sockaddr_un socket_address;
359 memset(&socket_address, 0,
sizeof(
struct sockaddr_un));
360 socket_address.sun_family = AF_UNIX;
364 " output directory an absolute path, else diod will fail!\n");
367 fatal_if(
sizeof(socket_address.sun_path) <= socket_path.length(),
368 "Incorrect length of socket path");
369 strncpy(socket_address.sun_path, socket_path.c_str(),
370 sizeof(socket_address.sun_path) - 1);
371 if (bind(socket_id, (
struct sockaddr*) &socket_address,
372 sizeof(
struct sockaddr_un)) == -1){
373 perror(
"Socket binding");
374 panic(
"Socket binding to %i failed - most likely the output dir" \
375 " and hence unused socket already exists \n", socket_id);
380 panic(
"Fork failed: %i\n", errno);
384 if (dup2(pipe_rfd[0], DIOD_RFD) == -1 ||
385 dup2(pipe_wfd[1], DIOD_WFD) == -1) {
387 panic(
"Failed to setup read/write pipes: %i\n",
393 "-d",
DTRACE(VIO9P) ?
"1" :
"0",
397 "-e",
p->root.c_str(),
400 "-l", socket_path.c_str(),
402 perror(
"Starting DIOD");
403 panic(
"Failed to execute diod to %s: %i\n",socket_path, errno);
407 inform(
"Started diod with PID %u, you might need to manually kill " \
408 " diod if gem5 crashes \n",
diod_pid);
420 return ret < 0 ? -errno : ret;
428 return ret < 0 ? -errno : ret;
445 perror(
"Killing diod process");
446 warn(
"Failed to kill diod using SIGTERM");
451 for (
unsigned i = 0;
i < 5;
i++) {
452 int wait_return = waitpid(
diod_pid, NULL, WNOHANG);
456 }
else if (wait_return == 0) {
462 warn(
"Failed in waitpid");
467 inform(
"Trying to kill diod with SIGKILL as SIGTERM failed \n");
469 perror(
"Killing diod process");
470 warn(
"Failed to kill diod using SIGKILL");
478 VirtIO9PDiodParams::create()
509 struct addrinfo hints, *result;
510 memset(&hints, 0,
sizeof(hints));
511 hints.ai_family = AF_UNSPEC;
512 hints.ai_socktype = SOCK_STREAM;
514 hints.ai_protocol = 0;
516 if ((ret = getaddrinfo(
p.server.c_str(),
p.port.c_str(),
517 &hints, &result)) != 0)
518 panic(
"getaddrinfo: %s\n", gai_strerror(ret));
520 DPRINTF(VIO9P,
"Connecting to 9p server '%s'.\n",
p.server);
521 for (
struct addrinfo *rp = result; rp; rp = rp->ai_next) {
522 fdSocket = socket(rp->ai_family, rp->ai_socktype,
526 }
else if (connect(
fdSocket, rp->ai_addr, rp->ai_addrlen) != -1) {
534 freeaddrinfo(result);
537 panic(
"Failed to connect to 9p server (%s:%s)",
p.server,
p.port);
543 panic(
"9P Socket disconnected!\n");
556 return ret < 0 ? -errno : ret;
564 return ret < 0 ? -errno : ret;
575 VirtIO9PSocketParams::create()
virtual ssize_t write(const uint8_t *data, size_t len)=0
Write data to the server behind the proxy.
void dumpMsg(const P9MsgHeader &header, const uint8_t *data, size_t size)
Dump a 9p RPC message on the debug output.
size_t size() const
Retrieve the size of this descriptor.
bool deviceUsed
Bool to track if the device has been used or not.
std::unique_ptr< SocketDataEvent > dataEvent
VirtIO9PBase(Params *params)
void produceDescriptor(VirtDescriptor *desc, uint32_t len)
Send a descriptor chain to the guest.
void recvTMsg(const P9MsgHeader &header, const uint8_t *data, size_t size) override
Handle incoming 9p RPC message.
void readConfig(PacketPtr pkt, Addr cfgOffset)
Read from the configuration space of a device.
#define UNSERIALIZE_SCALAR(scalar)
ByteOrder byteOrder(const ThreadContext *tc)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
ssize_t read(uint8_t *data, size_t len)
Read data from the server behind the proxy.
void serverDataReady()
Notification of pending data from server.
void registerQueue(VirtQueue &queue)
Register a new VirtQueue with the device model.
Base class for all VirtIO-based devices.
void readAll(uint8_t *data, size_t len)
Convenience function that reads exactly len bytes.
int fd_to_diod
fd for data pipe going to diod (write end)
VirtIO9PDiod(Params *params)
std::map< P9MsgType, P9MsgInfo > P9MsgInfoMap
void schedule(PollEvent *event)
std::string resolve(const std::string &name) const
Returns relative file names prepended with name of this directory.
#define P9MSG(type, name)
VirtIO 9p proxy that communicates with the diod 9p server using pipes.
int fd_from_diod
fd for data pipe coming from diod (read end)
std::map< P9Tag, VirtDescriptor * > pendingTransactions
Map between 9p transaction tags and descriptors where they appeared.
static bool isAbsolute(const std::string &name)
Test if a path is absolute.
VirtIO9PSocket(Params *params)
T htop9(T v)
Convert host byte order to p9 byte order (LE)
virtual ~VirtIO9PSocket()
void terminateDiod()
Kill the diod child process at the end of the simulation.
const size_t configSize
Size of the device's configuration space.
void registerExitCallback(const std::function< void()> &callback)
Register an exit callback.
VirtIO9PProxy(Params *params)
std::unique_ptr< DiodDataEvent > dataEvent
virtual ssize_t read(uint8_t *data, size_t len)=0
Read data from the server behind the proxy.
void startDiod()
Start diod and setup the communication pipes.
ssize_t write(const uint8_t *data, size_t len)
Write data to the server behind the proxy.
void startup()
startup() is the final initialization call before simulation.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
T htog(T value, ByteOrder guest_byte_order)
void readConfigBlob(PacketPtr pkt, Addr cfgOffset, const uint8_t *cfg)
Read configuration data from a device structure.
void writeAll(const uint8_t *data, size_t len)
Convenience function that writes exactly len bytes.
int fdSocket
Socket connected to the 9p server.
VirtIO9PBaseParams Params
void chainWrite(size_t offset, const uint8_t *src, size_t size)
Write to a descriptor chain.
This class implements a VirtIO transport layer for the 9p network file system.
static const P9MsgInfoMap p9_msg_info
void sendRMsg(const P9MsgHeader &header, const uint8_t *data, size_t size)
Send a 9p RPC message reply.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
const Params * params() const
T p9toh(T v)
Convert p9 byte order (LE) to host byte order.
#define SERIALIZE_SCALAR(scalar)
#define DDUMP(x, data, count)
DPRINTF is a debugging trace facility that allows one to selectively enable tracing statements.
void onNotifyDescriptor(VirtDescriptor *desc)
Notify queue of pending incoming descriptor.
VirtIO 9p proxy base class.
void socketDisconnect()
9p server disconnect notification
void chainRead(size_t offset, uint8_t *dst, size_t size) const
Read the contents of a descriptor chain.
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
int diod_pid
PID of diod process.
VirtIO 9p proxy that communicates with a 9p server over tcp sockets.
bool isOutgoing() const
Check if this is a write-only descriptor (outgoing data).
virtual void recvTMsg(const P9MsgHeader &header, const uint8_t *data, size_t size)=0
Handle incoming 9p RPC message.
std::ostream CheckpointOut
P9MsgInfo(P9MsgType _type, std::string _name)
void serialize(CheckpointOut &cp) const override
Serialize an object.
void serialize(CheckpointOut &cp) const override
Serialize an object.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
ssize_t write(const uint8_t *data, size_t len)
Write data to the server behind the proxy.
void startup()
startup() is the final initialization call before simulation.
void kick()
Inform the guest of available buffers.
VirtIO 9p configuration structure.
void connectSocket()
Try to resolve the server name and connect to the 9p server.
ByteOrder byteOrder
The byte order of the queues, descriptors, etc.
ssize_t read(uint8_t *data, size_t len)
Read data from the server behind the proxy.
VirtDescriptor * next() const
Get the pointer to the next descriptor in a chain.
std::unique_ptr< Config > config
Currently active configuration (host byte order)
VirtIO descriptor (chain) wrapper.
#define panic(...)
This implements a cprintf based panic() function.
Generated on Wed Sep 30 2020 14:02:11 for gem5 by doxygen 1.8.17