All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Huth <thuth@redhat.com>
To: qemu-devel@nongnu.org,
	Christian Borntraeger <borntraeger@de.ibm.com>,
	Cornelia Huck <cohuck@redhat.com>
Cc: Alexander Graf <agraf@suse.de>,
	Farhan Ali <alifm@linux.vnet.ibm.com>,
	David Hildenbrand <david@redhat.com>,
	Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>,
	Alexey Kardashevskiy <aik@ozlabs.ru>
Subject: [Qemu-devel] [PATCH v3 09/10] pc-bios/s390-ccw: Add virtio-net driver code
Date: Mon, 10 Jul 2017 17:32:39 +0200	[thread overview]
Message-ID: <1499700760-4777-10-git-send-email-thuth@redhat.com> (raw)
In-Reply-To: <1499700760-4777-1-git-send-email-thuth@redhat.com>

The driver provides the recv() and send() functions which will
be required by SLOF's libnet code for receiving and sending
packets.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 pc-bios/s390-ccw/netboot.mak  |   2 +-
 pc-bios/s390-ccw/virtio-net.c | 133 ++++++++++++++++++++++++++++++++++++++++++
 pc-bios/s390-ccw/virtio.c     |   9 ++-
 pc-bios/s390-ccw/virtio.h     |  14 ++++-
 4 files changed, 153 insertions(+), 5 deletions(-)
 create mode 100644 pc-bios/s390-ccw/virtio-net.c

diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak
index 1eaa0d8..dd9119a 100644
--- a/pc-bios/s390-ccw/netboot.mak
+++ b/pc-bios/s390-ccw/netboot.mak
@@ -1,7 +1,7 @@
 
 SLOF_DIR := $(SRC_PATH)/roms/SLOF
 
-NETOBJS := start.o sclp.o virtio.o netmain.o sbrk.o libc.a
+NETOBJS := start.o sclp.o virtio.o virtio-net.o netmain.o sbrk.o libc.a
 
 LIBC_INC := -I$(SLOF_DIR)/lib/libc/include
 LIBNET_INC := -I$(SLOF_DIR)/lib/libnet
diff --git a/pc-bios/s390-ccw/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c
new file mode 100644
index 0000000..804e7af
--- /dev/null
+++ b/pc-bios/s390-ccw/virtio-net.c
@@ -0,0 +1,133 @@
+/*
+ * Virtio-net driver for the s390-ccw firmware
+ *
+ * Copyright 2017 Thomas Huth, Red Hat Inc.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <ethernet.h>
+#include "s390-ccw.h"
+#include "virtio.h"
+
+#ifndef DEBUG_VIRTIO_NET
+#define DEBUG_VIRTIO_NET 0
+#endif
+
+#define VIRTIO_NET_F_MAC_BIT  (1 << 5)
+
+#define VQ_RX 0         /* Receive queue */
+#define VQ_TX 1         /* Transmit queue */
+
+struct VirtioNetHdr {
+    uint8_t flags;
+    uint8_t gso_type;
+    uint16_t hdr_len;
+    uint16_t gso_size;
+    uint16_t csum_start;
+    uint16_t csum_offset;
+    /*uint16_t num_buffers;*/ /* Only with VIRTIO_NET_F_MRG_RXBUF or VIRTIO1 */
+};
+typedef struct VirtioNetHdr VirtioNetHdr;
+
+static uint16_t rx_last_idx;  /* Last index in receive queue "used" ring */
+
+int virtio_net_init(void *mac_addr)
+{
+    VDev *vdev = virtio_get_device();
+    VRing *rxvq = &vdev->vrings[VQ_RX];
+    uint32_t guestfeats[2] = { VIRTIO_NET_F_MAC_BIT, 0 };
+    void *buf;
+    int i;
+
+    virtio_setup_ccw(vdev, guestfeats);
+
+    memcpy(mac_addr, vdev->config.net.mac, ETH_ALEN);
+
+    for (i = 0; i < 64; i++) {
+        buf = malloc(ETH_MTU_SIZE + sizeof(VirtioNetHdr));
+        IPL_assert(buf != NULL, "Can not allocate memory for receive buffers");
+        vring_send_buf(rxvq, buf, ETH_MTU_SIZE + sizeof(VirtioNetHdr),
+                       VRING_DESC_F_WRITE);
+    }
+    vring_notify(rxvq);
+
+    return 0;
+}
+
+int send(int fd, const void *buf, int len, int flags)
+{
+    VirtioNetHdr tx_hdr;
+    VDev *vdev = virtio_get_device();
+    VRing *txvq = &vdev->vrings[VQ_TX];
+
+    /* Set up header - we do not use anything special, so simply clear it */
+    memset(&tx_hdr, 0, sizeof(tx_hdr));
+
+    vring_send_buf(txvq, &tx_hdr, sizeof(tx_hdr), VRING_DESC_F_NEXT);
+    vring_send_buf(txvq, (void *)buf, len, VRING_HIDDEN_IS_CHAIN);
+    while (!vr_poll(txvq)) {
+        yield();
+    }
+    if (drain_irqs(txvq->schid)) {
+        puts("send: drain irqs failed");
+        return -1;
+    }
+
+    return len;
+}
+
+int recv(int fd, void *buf, int maxlen, int flags)
+{
+    VDev *vdev = virtio_get_device();
+    VRing *rxvq = &vdev->vrings[VQ_RX];
+    int len, id;
+    uint8_t *pkt;
+
+    if (rx_last_idx == rxvq->used->idx) {
+        return 0;
+    }
+
+    len = rxvq->used->ring[rx_last_idx % rxvq->num].len - sizeof(VirtioNetHdr);
+    if (len > maxlen) {
+        puts("virtio-net: Receive buffer too small");
+        len = maxlen;
+    }
+    id = rxvq->used->ring[rx_last_idx % rxvq->num].id % rxvq->num;
+    pkt = (uint8_t *)(rxvq->desc[id].addr + sizeof(VirtioNetHdr));
+
+#if DEBUG_VIRTIO_NET   /* Dump packet */
+    int i;
+    printf("\nbuf %p: len=%i\n", (void *)rxvq->desc[id].addr, len);
+    for (i = 0; i < 64; i++) {
+        printf(" %02x", pkt[i]);
+        if ((i % 16) == 15) {
+            printf("\n");
+        }
+    }
+    printf("\n");
+#endif
+
+    /* Copy data to destination buffer */
+    memcpy(buf, pkt, len);
+
+    /* Mark buffer as available to the host again */
+    rxvq->avail->ring[rxvq->avail->idx % rxvq->num] = id;
+    rxvq->avail->idx = rxvq->avail->idx + 1;
+    vring_notify(rxvq);
+
+    /* Move index to next entry */
+    rx_last_idx = rx_last_idx + 1;
+
+    return len;
+}
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index e3dcfd3..4cd70df 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -150,7 +150,7 @@ static void vring_init(VRing *vr, VqInfo *info)
     debug_print_addr("init vr", vr);
 }
 
-static bool vring_notify(VRing *vr)
+bool vring_notify(VRing *vr)
 {
     vr->cookie = virtio_notify(vr->schid, vr->id, vr->cookie);
     return vr->cookie >= 0;
@@ -189,7 +189,7 @@ ulong get_second(void)
     return (get_clock() >> 12) / 1000000;
 }
 
-static int vr_poll(VRing *vr)
+int vr_poll(VRing *vr)
 {
     if (vr->used->idx == vr->used_idx) {
         vring_notify(vr);
@@ -266,6 +266,11 @@ void virtio_setup_ccw(VDev *vdev, uint32_t guestfeats[2])
     run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0);
 
     switch (vdev->senseid.cu_model) {
+    case VIRTIO_ID_NET:
+        vdev->nr_vqs = 2;
+        vdev->cmd_vr_idx = 0;
+        cfg_size = sizeof(vdev->config.net);
+        break;
     case VIRTIO_ID_BLOCK:
         vdev->nr_vqs = 1;
         vdev->cmd_vr_idx = 0;
diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
index e3d7150..c81af23 100644
--- a/pc-bios/s390-ccw/virtio.h
+++ b/pc-bios/s390-ccw/virtio.h
@@ -11,8 +11,6 @@
 #ifndef VIRTIO_H
 #define VIRTIO_H
 
-#include "s390-ccw.h"
-
 /* Status byte for guest to report progress, and synchronize features. */
 /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
 #define VIRTIO_CONFIG_S_ACKNOWLEDGE     1
@@ -254,6 +252,13 @@ struct ScsiDevice {
 };
 typedef struct ScsiDevice ScsiDevice;
 
+struct VirtioNetConfig {
+    uint8_t mac[6];
+    /* uint16_t status; */               /* Only with VIRTIO_NET_F_STATUS */
+    /* uint16_t max_virtqueue_pairs; */  /* Only with VIRTIO_NET_F_MQ */
+};
+typedef struct VirtioNetConfig VirtioNetConfig;
+
 struct VDev {
     int nr_vqs;
     VRing *vrings;
@@ -266,6 +271,7 @@ struct VDev {
     union {
         VirtioBlkConfig blk;
         VirtioScsiConfig scsi;
+        VirtioNetConfig net;
     } config;
     ScsiDevice *scsi_device;
     bool is_cdrom;
@@ -291,10 +297,14 @@ struct VirtioCmd {
 };
 typedef struct VirtioCmd VirtioCmd;
 
+bool vring_notify(VRing *vr);
 int drain_irqs(SubChannelId schid);
 void vring_send_buf(VRing *vr, void *p, int len, int flags);
+int vr_poll(VRing *vr);
 int vring_wait_reply(void);
 int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd);
 void virtio_setup_ccw(VDev *vdev, uint32_t guestfeats[2]);
 
+int virtio_net_init(void *mac_addr);
+
 #endif /* VIRTIO_H */
-- 
1.8.3.1

  parent reply	other threads:[~2017-07-10 15:33 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-10 15:32 [Qemu-devel] [PATCH v3 00/10] Implement network booting directly into the s390-ccw BIOS Thomas Huth
2017-07-10 15:32 ` [Qemu-devel] [PATCH v3 01/10] pc-bios/s390-ccw: Move libc functions to separate header Thomas Huth
2017-07-11  7:49   ` Cornelia Huck
2017-07-10 15:32 ` [Qemu-devel] [PATCH v3 02/10] pc-bios/s390-ccw: Move ebc2asc to sclp.c Thomas Huth
2017-07-11  9:43   ` David Hildenbrand
2017-07-10 15:32 ` [Qemu-devel] [PATCH v3 03/10] pc-bios/s390-ccw: Move virtio-block related functions into a separate file Thomas Huth
2017-07-11  7:53   ` Cornelia Huck
2017-07-11  9:45   ` David Hildenbrand
2017-07-10 15:32 ` [Qemu-devel] [PATCH v3 04/10] pc-bios/s390-ccw: Add a write() function for stdio Thomas Huth
2017-07-11  9:47   ` David Hildenbrand
2017-07-10 15:32 ` [Qemu-devel] [PATCH v3 05/10] pc-bios/s390-ccw: Move byteswap functions to a separate header Thomas Huth
2017-07-11  7:39   ` Christian Borntraeger
2017-07-11  7:59   ` Cornelia Huck
2017-07-11  8:52     ` Thomas Huth
2017-07-11  9:05       ` Cornelia Huck
2017-07-10 15:32 ` [Qemu-devel] [PATCH v3 06/10] pc-bios/s390-ccw: Add code for virtio feature negotiation Thomas Huth
2017-07-11  8:47   ` Cornelia Huck
2017-07-10 15:32 ` [Qemu-devel] [PATCH v3 07/10] roms/SLOF: Update submodule to latest status Thomas Huth
2017-07-10 15:32 ` [Qemu-devel] [PATCH v3 08/10] pc-bios/s390-ccw: Add core files for the network bootloading program Thomas Huth
2017-07-11  8:52   ` Cornelia Huck
2017-07-11 13:30     ` Thomas Huth
2017-07-10 15:32 ` Thomas Huth [this message]
2017-07-11  8:57   ` [Qemu-devel] [PATCH v3 09/10] pc-bios/s390-ccw: Add virtio-net driver code Cornelia Huck
2017-07-10 15:32 ` [Qemu-devel] [PATCH v3 10/10] pc-bios/s390-ccw: Link libnet into the netboot image and do the TFTP load Thomas Huth
2017-07-11  9:01   ` Cornelia Huck
2017-07-11  7:46 ` [Qemu-devel] [PATCH v3 00/10] Implement network booting directly into the s390-ccw BIOS Christian Borntraeger
2017-07-11 13:37 ` no-reply
2017-07-11 14:04 ` no-reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1499700760-4777-10-git-send-email-thuth@redhat.com \
    --to=thuth@redhat.com \
    --cc=agraf@suse.de \
    --cc=aik@ozlabs.ru \
    --cc=alifm@linux.vnet.ibm.com \
    --cc=borntraeger@de.ibm.com \
    --cc=cohuck@redhat.com \
    --cc=david@redhat.com \
    --cc=mihajlov@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.