44 #include <netinet/in.h>
45 #include <sys/socket.h>
46 #include <sys/types.h>
49 #include "debug/VIO9P.hh"
50 #include "debug/VIO9PData.hh"
51 #include "params/VirtIO9PBase.hh"
52 #include "params/VirtIO9PDiod.hh"
53 #include "params/VirtIO9PProxy.hh"
54 #include "params/VirtIO9PSocket.hh"
67 #define P9MSG(type, name) \
68 { (type), P9MsgInfo((type), "T" # name ) }, \
69 { (type + 1), P9MsgInfo((type + 1), "R" # name ) }
83 P9MSG(32, XATTRCREATE),
114 queue(params->
system->physProxy, params->queueSize, *this)
119 memcpy(
config->tag, params->tag.c_str(), params->tag.size());
138 DPRINTF(VIO9P,
"Got input data descriptor (len: %i)\n", desc->
size());
142 desc->
chainRead(0, (uint8_t *)&header,
sizeof(header));
143 header =
p9toh(header);
145 uint8_t
data[header.len -
sizeof(header)];
161 DPRINTF(VIO9P,
"Sending RMsg\n");
164 assert(header.
len >=
sizeof(header));
172 out_desc = out_desc->
next();
174 panic(
"sendRMsg: Framing error, no output descriptor.\n");
179 out_desc->
chainWrite(0, (uint8_t *)&header_out,
sizeof(header_out));
180 out_desc->
chainWrite(
sizeof(header_out), data, size);
193 const P9MsgInfoMap::const_iterator it_msg(
p9_msg_info.find(header.
type));
196 DPRINTF(VIO9P,
"P9Msg[len = %i, type = %s (%i), tag = %i]\n",
199 DPRINTF(VIO9P,
"P9Msg[len = %i, type = Unknown (%i), tag = %i]\n",
202 DDUMP(VIO9PData, data, size);
221 warn(
"Serializing VirtIO9Base device after device has been used. It is "
222 "likely that state will be lost, and that the device will cease "
236 warn(
"Unserializing VirtIO9Base device after device has been used. It is "
237 "likely that state has been lost, and that the device will cease "
249 assert(header.
len ==
sizeof(header) + size);
252 uint8_t out[header.
len];
254 memcpy(out, (uint8_t *)&header_out,
sizeof(header_out));
255 memcpy(out +
sizeof(header_out), data, size);
256 writeAll(out,
sizeof(header_out) + size);
263 readAll((uint8_t *)&header,
sizeof(header));
264 header =
p9toh(header);
266 const ssize_t payload_len(header.
len -
sizeof(header));
268 panic(
"Payload length is negative!\n");
269 uint8_t
data[payload_len];
272 sendRMsg(header, data, payload_len);
281 while ((ret =
read(data, len)) == -EAGAIN)
284 panic(
"readAll: Read failed: %i\n", -ret);
296 while ((ret =
write(data, len)) == -EAGAIN)
299 panic(
"writeAll: write failed: %i\n", -ret);
310 fd_to_diod(-1), fd_from_diod(-1), diod_pid(-1)
332 const int DIOD_RFD = 3;
333 const int DIOD_WFD = 4;
335 const char *diod(p->diod.c_str());
337 if (pipe(pipe_rfd) == -1 || pipe(pipe_wfd) == -1)
338 panic(
"Failed to create DIOD pipes: %i\n", errno);
345 panic(
"Fork failed: %i\n", errno);
349 if (dup2(pipe_rfd[0], DIOD_RFD) == -1 ||
350 dup2(pipe_wfd[1], DIOD_WFD) == -1) {
352 panic(
"Failed to setup read/write pipes: %i\n",
360 "-e", p->root.c_str(),
364 panic(
"Failed to execute diod: %i\n", errno);
379 return ret < 0 ? -errno : ret;
387 return ret < 0 ? -errno : ret;
397 VirtIO9PDiodParams::create()
428 struct addrinfo hints, *result;
429 memset(&hints, 0,
sizeof(hints));
430 hints.ai_family = AF_UNSPEC;
431 hints.ai_socktype = SOCK_STREAM;
433 hints.ai_protocol = 0;
435 if ((ret = getaddrinfo(p.server.c_str(), p.port.c_str(),
436 &hints, &result)) != 0)
437 panic(
"getaddrinfo: %s\n", gai_strerror(ret));
439 DPRINTF(VIO9P,
"Connecting to 9p server '%s'.\n", p.server);
440 for (
struct addrinfo *rp = result; rp; rp = rp->ai_next) {
441 fdSocket = socket(rp->ai_family, rp->ai_socktype,
445 }
else if (connect(
fdSocket, rp->ai_addr, rp->ai_addrlen) != -1) {
453 freeaddrinfo(result);
456 panic(
"Failed to connect to 9p server (%s:%s)", p.server, p.port);
462 panic(
"9P Socket disconnected!\n");
471 ret = ::recv(
fdSocket, (
void *)data, len, 0);
475 return ret < 0 ? -errno : ret;
482 int ret(::send(
fdSocket, (
const void *)data, len, 0));
483 return ret < 0 ? -errno : ret;
494 VirtIO9PSocketParams::create()
void startup()
startup() is the final initialization call before simulation.
ssize_t read(uint8_t *data, size_t len)
Read data from the server behind the proxy.
This class implements a VirtIO transport layer for the 9p network file system.
Base class for all VirtIO-based devices.
ssize_t read(uint8_t *data, size_t len)
Read data from the server behind the proxy.
VirtIO 9p proxy that communicates with a 9p server over tcp sockets.
void socketDisconnect()
9p server disconnect notification
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 serialize(CheckpointOut &cp) const override
Serialize an object.
#define DDUMP(x, data, count)
const Params * params() const
std::map< P9Tag, VirtDescriptor * > pendingTransactions
Map between 9p transaction tags and descriptors where they appeared.
T p9toh(T v)
Convert p9 byte order (LE) to host byte order.
int fd_to_diod
fd for data pipe going to diod (write end)
void readConfig(PacketPtr pkt, Addr cfgOffset)
Read from the configuration space of a device.
void sendRMsg(const P9MsgHeader &header, const uint8_t *data, size_t size)
Send a 9p RPC message reply.
virtual void recvTMsg(const P9MsgHeader &header, const uint8_t *data, size_t size)=0
Handle incoming 9p RPC message.
std::map< P9MsgType, P9MsgInfo > P9MsgInfoMap
virtual ssize_t write(const uint8_t *data, size_t len)=0
Write data to the server behind the proxy.
#define P9MSG(type, name)
int fd_from_diod
fd for data pipe coming from diod (read end)
void serialize(CheckpointOut &cp) const override
Serialize an object.
void schedule(PollEvent *event)
static const P9MsgInfoMap p9_msg_info
void produceDescriptor(VirtDescriptor *desc, uint32_t len)
Send a descriptor chain to the guest.
void writeAll(const uint8_t *data, size_t len)
Convenience function that writes exactly len bytes.
std::unique_ptr< SocketDataEvent > dataEvent
#define UNSERIALIZE_SCALAR(scalar)
virtual ~VirtIO9PSocket()
T htov_legacy(T v)
Convert host endianness to legacy VirtIO endianness.
void startup()
startup() is the final initialization call before simulation.
VirtIO9PDiod(Params *params)
void serverDataReady()
Notification of pending data from server.
VirtIO9PSocket(Params *params)
void chainRead(size_t offset, uint8_t *dst, size_t size) const
Read the contents of a descriptor chain.
void kick()
Inform the guest of available buffers.
void chainWrite(size_t offset, const uint8_t *src, size_t size)
Write to a descriptor chain.
bool deviceUsed
Bool to track if the device has been used or not.
void onNotifyDescriptor(VirtDescriptor *desc)
Notify queue of pending incoming descriptor.
VirtIO descriptor (chain) wrapper.
ssize_t write(const uint8_t *data, size_t len)
Write data to the server behind the proxy.
P9MsgInfo(P9MsgType _type, std::string _name)
void recvTMsg(const P9MsgHeader &header, const uint8_t *data, size_t size) override
Handle incoming 9p RPC message.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
VirtIO9PBaseParams Params
size_t size() const
Retrieve the size of this descriptor.
#define SERIALIZE_SCALAR(scalar)
void startDiod()
Start diod and setup the communication pipes.
VirtDescriptor * next() const
Get the pointer to the next descriptor in a chain.
void registerQueue(VirtQueue &queue)
Register a new VirtQueue with the device model.
void readAll(uint8_t *data, size_t len)
Convenience function that reads exactly len bytes.
T htop9(T v)
Convert host byte order to p9 byte order (LE)
std::ostream CheckpointOut
VirtIO 9p configuration structure.
VirtIO9PBase(Params *params)
int diod_pid
PID of diod process.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
bool isOutgoing() const
Check if this is a write-only descriptor (outgoing data).
void connectSocket()
Try to resolve the server name and connect to the 9p server.
void dumpMsg(const P9MsgHeader &header, const uint8_t *data, size_t size)
Dump a 9p RPC message on the debug output.
VirtIO 9p proxy that communicates with the diod 9p server using pipes.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
std::unique_ptr< Config > config
Currently active configuration (host byte order)
void readConfigBlob(PacketPtr pkt, Addr cfgOffset, const uint8_t *cfg)
Read configuration data from a device structure.
VirtIO9PProxy(Params *params)
int fdSocket
Socket connected to the 9p server.
const size_t configSize
Size of the device's configuration space.
VirtIO 9p proxy base class.
ssize_t write(const uint8_t *data, size_t len)
Write data to the server behind the proxy.