Commit 7f925101 authored by Antoine Kaufmann's avatar Antoine Kaufmann
Browse files

now dummy nic works with qemu for basic mmio/pio read/write :-)

parent 79d54f3f
CFLAGS += -Wall -Wextra -Wno-unused-parameter -O3
dummy_nic: dummy_nic.o poll.o utils.o
all: dummy_nic
clean:
......
......@@ -21,127 +21,20 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <sys/un.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <unistd.h>
#include "../proto/cosim_pcie_proto.h"
#include "dummy_nic.h"
#define D2H_ELEN (4096 + 64)
#define D2H_ENUM 1024
uint8_t *d2h_queue;
size_t d2h_pos;
#define H2D_ELEN (64)
#define H2D_ENUM 1024
uint8_t *h2d_queue;
size_t h2d_pos;
static int uxsocket_init(const char *path)
{
int fd;
struct sockaddr_un saun;
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("uxsocket_init: socket failed");
goto error_exit;
}
memset(&saun, 0, sizeof(saun));
saun.sun_family = AF_UNIX;
memcpy(saun.sun_path, path, strlen(path));
if (bind(fd, (struct sockaddr *) &saun, sizeof(saun))) {
perror("uxsocket_init: bind failed");
goto error_close;
}
if (listen(fd, 5)) {
perror("uxsocket_init: listen failed");
goto error_close;
}
return fd;
error_close:
close(fd);
error_exit:
return -1;
}
static int uxsocket_send(int connfd, void *data, size_t len, int fd)
{
ssize_t tx;
struct iovec iov = {
.iov_base = data,
.iov_len = len,
};
union {
char buf[CMSG_SPACE(sizeof(int))];
struct cmsghdr align;
} u;
struct msghdr msg = {
.msg_name = NULL,
.msg_namelen = 0,
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = u.buf,
.msg_controllen = 0,
.msg_flags = 0,
};
struct cmsghdr *cmsg = &u.align;
if (fd >= 0) {
msg.msg_controllen = sizeof(u.buf);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
*(int *) CMSG_DATA(cmsg) = fd;
}
if((tx = sendmsg(connfd, &msg, 0)) != (ssize_t) len) {
fprintf(stderr, "tx == %zd\n", tx);
return -1;
}
return 0;
}
static int shm_create(const char *path, size_t size, void **addr)
{
int fd;
void *p;
if ((fd = open(path, O_CREAT | O_RDWR, 0666)) == -1) {
perror("util_create_shmsiszed: open failed");
goto error_out;
}
if (ftruncate(fd, size) != 0) {
perror("util_create_shmsiszed: ftruncate failed");
goto error_remove;
}
if ((p = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, fd, 0)) == (void *) -1)
{
perror("util_create_shmsiszed: mmap failed");
goto error_remove;
}
memset(p, 0, size);
*addr = p;
return fd;
error_remove:
close(fd);
unlink(path);
error_out:
return -1;
}
int main(int argc, char *argv[])
{
......@@ -166,6 +59,11 @@ int main(int argc, char *argv[])
d2h_off = 0;
h2d_off = (uint64_t) D2H_ELEN * D2H_ENUM;
d2h_queue = (uint8_t *) shmptr + d2h_off;
h2d_queue = (uint8_t *) shmptr + h2d_off;
d2h_pos = h2d_pos = 0;
struct cosim_pcie_proto_dev_intro di;
memset(&di, 0, sizeof(di));
......@@ -197,7 +95,7 @@ int main(int argc, char *argv[])
printf("host info received\n");
while (1) {
pause();
poll_h2d();
}
close(pci_lfd);
......
/*
* Copyright 2020 Max Planck Institute for Software Systems
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stddef.h>
#include <stdio.h>
#include "../proto/cosim_pcie_proto.h"
#define D2H_ELEN (4096 + 64)
#define D2H_ENUM 1024
#define H2D_ELEN (4096 + 64)
#define H2D_ENUM 1024
extern uint8_t *d2h_queue;
extern size_t d2h_pos;
extern uint8_t *h2d_queue;
extern size_t h2d_pos;
/* poll.c */
void poll_h2d(void);
/* utils.c */
int uxsocket_init(const char *path);
int uxsocket_send(int connfd, void *data, size_t len, int fd);
int shm_create(const char *path, size_t size, void **addr);
/*
* Copyright 2020 Max Planck Institute for Software Systems
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "dummy_nic.h"
static volatile union cosim_pcie_proto_d2h *d2h_alloc(void)
{
volatile union cosim_pcie_proto_d2h *msg =
(volatile union cosim_pcie_proto_d2h *)
(d2h_queue + d2h_pos * D2H_ELEN);
if ((msg->dummy.own_type & COSIM_PCIE_PROTO_D2H_OWN_MASK) !=
COSIM_PCIE_PROTO_D2H_OWN_DEV)
{
fprintf(stderr, "d2h_alloc: no entry available\n");
abort();
}
d2h_pos = (d2h_pos + 1) % D2H_ENUM;
return msg;
}
static void h2d_read(volatile struct cosim_pcie_proto_h2d_read *read)
{
volatile union cosim_pcie_proto_d2h *msg;
volatile struct cosim_pcie_proto_d2h_readcomp *rc;
uint64_t val;
msg = d2h_alloc();
rc = &msg->readcomp;
val = read->offset + 42;
printf("read(bar=%u, off=%lu, len=%u) = %lu\n", read->bar, read->offset,
read->len, val);
memcpy((void *) rc->data, &val, read->len);
rc->req_id = read->req_id;
//WMB();
rc->own_type = COSIM_PCIE_PROTO_D2H_MSG_READCOMP |
COSIM_PCIE_PROTO_D2H_OWN_HOST;
}
static void h2d_write(volatile struct cosim_pcie_proto_h2d_write *write)
{
volatile union cosim_pcie_proto_d2h *msg;
volatile struct cosim_pcie_proto_d2h_writecomp *wc;
uint64_t val;
msg = d2h_alloc();
wc = &msg->writecomp;
val = 0;
memcpy(&val, (void *) write->data, write->len);
printf("write(bar=%u, off=%lu, len=%u, val=%lu)\n", write->bar,
write->offset, write->len, val);
wc->req_id = write->req_id;
//WMB();
wc->own_type = COSIM_PCIE_PROTO_D2H_MSG_WRITECOMP |
COSIM_PCIE_PROTO_D2H_OWN_HOST;
}
void poll_h2d(void)
{
volatile union cosim_pcie_proto_h2d *msg =
(volatile union cosim_pcie_proto_h2d *)
(h2d_queue + h2d_pos * H2D_ELEN);
uint8_t type;
/* message not ready */
if ((msg->dummy.own_type & COSIM_PCIE_PROTO_H2D_OWN_MASK) !=
COSIM_PCIE_PROTO_H2D_OWN_DEV)
return;
type = msg->dummy.own_type & COSIM_PCIE_PROTO_H2D_MSG_MASK;
switch (type) {
case COSIM_PCIE_PROTO_H2D_MSG_READ:
h2d_read(&msg->read);
break;
case COSIM_PCIE_PROTO_H2D_MSG_WRITE:
h2d_write(&msg->write);
break;
default:
fprintf(stderr, "poll_h2d: unsupported type=%u\n", type);
}
//WMB();
msg->dummy.own_type = type | COSIM_PCIE_PROTO_H2D_OWN_HOST;
h2d_pos = (h2d_pos + 1) % H2D_ENUM;
}
/*
* Copyright 2020 Max Planck Institute for Software Systems
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <unistd.h>
#include "dummy_nic.h"
int uxsocket_init(const char *path)
{
int fd;
struct sockaddr_un saun;
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("uxsocket_init: socket failed");
goto error_exit;
}
memset(&saun, 0, sizeof(saun));
saun.sun_family = AF_UNIX;
memcpy(saun.sun_path, path, strlen(path));
if (bind(fd, (struct sockaddr *) &saun, sizeof(saun))) {
perror("uxsocket_init: bind failed");
goto error_close;
}
if (listen(fd, 5)) {
perror("uxsocket_init: listen failed");
goto error_close;
}
return fd;
error_close:
close(fd);
error_exit:
return -1;
}
int uxsocket_send(int connfd, void *data, size_t len, int fd)
{
ssize_t tx;
struct iovec iov = {
.iov_base = data,
.iov_len = len,
};
union {
char buf[CMSG_SPACE(sizeof(int))];
struct cmsghdr align;
} u;
struct msghdr msg = {
.msg_name = NULL,
.msg_namelen = 0,
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = u.buf,
.msg_controllen = 0,
.msg_flags = 0,
};
struct cmsghdr *cmsg = &u.align;
if (fd >= 0) {
msg.msg_controllen = sizeof(u.buf);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
*(int *) CMSG_DATA(cmsg) = fd;
}
if((tx = sendmsg(connfd, &msg, 0)) != (ssize_t) len) {
fprintf(stderr, "tx == %zd\n", tx);
return -1;
}
return 0;
}
int shm_create(const char *path, size_t size, void **addr)
{
int fd;
void *p;
if ((fd = open(path, O_CREAT | O_RDWR, 0666)) == -1) {
perror("util_create_shmsiszed: open failed");
goto error_out;
}
if (ftruncate(fd, size) != 0) {
perror("util_create_shmsiszed: ftruncate failed");
goto error_remove;
}
if ((p = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, fd, 0)) == (void *) -1)
{
perror("util_create_shmsiszed: mmap failed");
goto error_remove;
}
memset(p, 0, size);
*addr = p;
return fd;
error_remove:
close(fd);
unlink(path);
error_out:
return -1;
}
1. Clone from here: `github.com:FreakyPenguin/qemu-cosim.git`
2. Build with `./configure --target-list=x86_64-softmmu --disable-werror --extra-cflags="-I$PATH_TO_THIS_REPO/proto" --enable-cosim-pci`
3. To run for example (only the last line is specific to this project):
3. run dummy nic: rm -rf /tmp/cosim-pci; ./dummy_nic
4. To run for example (only the last line is specific to this project):
```
x86_64-softmmu/qemu-system-x86_64 \
-machine q35 -cpu host \
......@@ -9,3 +10,6 @@ x86_64-softmmu/qemu-system-x86_64 \
-chardev socket,path=/tmp/cosim-pci,id=cosimcd \
-device cosim-pci,chardev=cosimcd
```
5. in vm test with:
* `for read: dd if=/sys/bus/pci/devices/0000\:00\:03.0/resource2 bs=1 skip=64 count=1`
* `for write: echo a | dd of=/sys/bus/pci/devices/0000\:00\:03.0/resource2 bs=1 seek=64 count=1`
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment