From patchwork Sun Oct 9 16:09:51 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikunj A Dadhania X-Patchwork-Id: 680065 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3ssSsM4QZ9z9sBR for ; Mon, 10 Oct 2016 03:10:31 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3ssSsM3ZBkzDrbg for ; Mon, 10 Oct 2016 03:10:31 +1100 (AEDT) X-Original-To: slof@lists.ozlabs.org Delivered-To: slof@lists.ozlabs.org Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3ssSsG5cpyzDrbq for ; Mon, 10 Oct 2016 03:10:26 +1100 (AEDT) Received: from pps.filterd (m0098413.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.17/8.16.0.17) with SMTP id u99G9eZr094813 for ; Sun, 9 Oct 2016 12:10:24 -0400 Received: from e23smtp07.au.ibm.com (e23smtp07.au.ibm.com [202.81.31.140]) by mx0b-001b2d01.pphosted.com with ESMTP id 25ykpqhmne-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Sun, 09 Oct 2016 12:10:24 -0400 Received: from localhost by e23smtp07.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 10 Oct 2016 02:10:21 +1000 Received: from d23dlp01.au.ibm.com (202.81.31.203) by e23smtp07.au.ibm.com (202.81.31.204) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 10 Oct 2016 02:10:18 +1000 Received: from d23relay10.au.ibm.com (d23relay10.au.ibm.com [9.190.26.77]) by d23dlp01.au.ibm.com (Postfix) with ESMTP id 57D8D2CE8054 for ; Mon, 10 Oct 2016 03:10:18 +1100 (EST) Received: from d23av02.au.ibm.com (d23av02.au.ibm.com [9.190.235.138]) by d23relay10.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u99GAIfb4915612 for ; Mon, 10 Oct 2016 03:10:18 +1100 Received: from d23av02.au.ibm.com (localhost [127.0.0.1]) by d23av02.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u99GAHZw021181 for ; Mon, 10 Oct 2016 03:10:18 +1100 Received: from abhimanyu.in.ibm.com ([9.79.232.158]) by d23av02.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u99GA2Sm020817; Mon, 10 Oct 2016 03:10:16 +1100 From: Nikunj A Dadhania To: slof@lists.ozlabs.org, thuth@redhat.com Date: Sun, 9 Oct 2016 21:39:51 +0530 X-Mailer: git-send-email 2.7.4 In-Reply-To: <1476029391-26067-1-git-send-email-nikunj@linux.vnet.ibm.com> References: <1476029391-26067-1-git-send-email-nikunj@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16100916-0044-0000-0000-000001EBAE1A X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16100916-0045-0000-0000-000005B586FE Message-Id: <1476029391-26067-4-git-send-email-nikunj@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-10-09_09:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=9 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1609300000 definitions=main-1610090281 Subject: [SLOF] [PATCH RFC v0 3/3] Add virtio-serial device support X-BeenThere: slof@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Patches for https://github.com/aik/SLOF" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: slof-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "SLOF" Add support for virtio serial device to be used as a console device. Currently, SLOF only supports spapr-vty device. With this addition virtio console can be used during boot. Signed-off-by: Nikunj A Dadhania --- board-qemu/slof/Makefile | 3 + board-qemu/slof/OF.fs | 24 +++- board-qemu/slof/pci-device_1af4_1003.fs | 25 ++++ board-qemu/slof/pci-device_1af4_1043.fs | 15 +++ board-qemu/slof/virtio-serial.fs | 95 +++++++++++++++ lib/libvirtio/Makefile | 2 +- lib/libvirtio/virtio-serial.c | 202 ++++++++++++++++++++++++++++++++ lib/libvirtio/virtio-serial.h | 28 +++++ lib/libvirtio/virtio.code | 33 ++++++ lib/libvirtio/virtio.in | 6 + 10 files changed, 426 insertions(+), 7 deletions(-) create mode 100644 board-qemu/slof/pci-device_1af4_1003.fs create mode 100644 board-qemu/slof/pci-device_1af4_1043.fs create mode 100644 board-qemu/slof/virtio-serial.fs create mode 100644 lib/libvirtio/virtio-serial.c create mode 100644 lib/libvirtio/virtio-serial.h diff --git a/board-qemu/slof/Makefile b/board-qemu/slof/Makefile index 940a15a..cf57f16 100644 --- a/board-qemu/slof/Makefile +++ b/board-qemu/slof/Makefile @@ -69,6 +69,8 @@ VIO_FFS_FILES = \ $(SLOFBRDDIR)/pci-device_1af4_1041.fs \ $(SLOFBRDDIR)/pci-device_1af4_1001.fs \ $(SLOFBRDDIR)/pci-device_1af4_1042.fs \ + $(SLOFBRDDIR)/pci-device_1af4_1003.fs \ + $(SLOFBRDDIR)/pci-device_1af4_1043.fs \ $(SLOFBRDDIR)/pci-device_1af4_1004.fs \ $(SLOFBRDDIR)/pci-device_1af4_1048.fs \ $(SLOFBRDDIR)/pci-device_1af4_1009.fs \ @@ -79,6 +81,7 @@ VIO_FFS_FILES = \ $(SLOFBRDDIR)/vio-veth.fs \ $(SLOFBRDDIR)/rtas-nvram.fs \ $(SLOFBRDDIR)/virtio-net.fs \ + $(SLOFBRDDIR)/virtio-serial.fs \ $(SLOFBRDDIR)/virtio-block.fs \ $(SLOFBRDDIR)/virtio-fs.fs \ $(SLOFBRDDIR)/dev-null.fs \ diff --git a/board-qemu/slof/OF.fs b/board-qemu/slof/OF.fs index c8df9ca..6b13e03 100644 --- a/board-qemu/slof/OF.fs +++ b/board-qemu/slof/OF.fs @@ -162,6 +162,10 @@ CREATE version-str 10 ALLOT : dump-display-write s" screen" find-alias IF drop terminal-write drop + ELSE + s" vsterm" find-alias IF + drop type + THEN THEN ; @@ -236,12 +240,20 @@ romfs-base 400000 0 ' claim CATCH IF ." claim failed!" cr 2drop THEN drop ." using hvterm" cr " hvterm" io ELSE - " /openprom" find-node ?dup IF - set-node - ." and no default found, creating dev-null" cr - " dev-null.fs" included - " devnull-console" io - 0 set-node + " vsterm" find-alias IF + drop + ." using vsterm" cr + " vsterm" io + false to store-prevga? + dump-display-buffer + ELSE + " /openprom" find-node ?dup IF + set-node + ." and no default found, creating dev-null" cr + " dev-null.fs" included + " devnull-console" io + 0 set-node + THEN THEN THEN THEN diff --git a/board-qemu/slof/pci-device_1af4_1003.fs b/board-qemu/slof/pci-device_1af4_1003.fs new file mode 100644 index 0000000..a7cd53b --- /dev/null +++ b/board-qemu/slof/pci-device_1af4_1003.fs @@ -0,0 +1,25 @@ +\ ***************************************************************************** +\ * Copyright (c) 2016 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ * IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ Handle virtio-serial device + +s" virtio [ serial ]" type cr + +my-space pci-device-generic-setup + +pci-master-enable +pci-mem-enable +pci-io-enable + +s" virtio-serial.fs" included + +pci-device-disable diff --git a/board-qemu/slof/pci-device_1af4_1043.fs b/board-qemu/slof/pci-device_1af4_1043.fs new file mode 100644 index 0000000..f044450 --- /dev/null +++ b/board-qemu/slof/pci-device_1af4_1043.fs @@ -0,0 +1,15 @@ +\ ***************************************************************************** +\ * Copyright (c) 2016 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ * IBM Corporation - initial implementation +\ ****************************************************************************/ + +\ Device ID 1044 is for virtio-serial non-transitional device. +\ Include the driver for virtio-serial +s" pci-device_1af4_1003.fs" included diff --git a/board-qemu/slof/virtio-serial.fs b/board-qemu/slof/virtio-serial.fs new file mode 100644 index 0000000..0f25a80 --- /dev/null +++ b/board-qemu/slof/virtio-serial.fs @@ -0,0 +1,95 @@ +\ ***************************************************************************** +\ * Copyright (c) 2016 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ * IBM Corporation - initial implementation +\ ****************************************************************************/ + +s" serial" device-type + +FALSE VALUE initialized? + +virtio-setup-vd VALUE virtiodev + +\ Quiesce the virtqueue of this device so that no more background +\ transactions can be pending. +: shutdown ( -- ) + initialized? IF + my-phandle node>path open-dev ?dup IF + virtiodev virtio-serial-shutdown + close-dev + THEN + FALSE to initialized? + THEN +; + +: virtio-serial-term-emit + virtiodev SWAP virtio-serial-putchar +; + +: virtio-serial-term-key? virtiodev virtio-serial-haschar ; +: virtio-serial-term-key BEGIN virtio-serial-term-key? UNTIL virtiodev virtio-serial-getchar ; + +\ Basic device initialization - which has only to be done once +: init ( -- ) +virtiodev virtio-serial-init drop + TRUE to initialized? + ['] virtio-serial-term-emit to emit + ['] virtio-serial-term-key to key + ['] virtio-serial-term-key? to key? + ['] shutdown add-quiesce-xt +; + +0 VALUE open-count + +\ Standard node "open" function +: open ( -- okay? ) + open-count 0= IF + open IF initialized? 0= IF init THEN + true + ELSE false exit + THEN + ELSE true THEN + open-count 1 + to open-count +; + +: close + open-count 0> IF + open-count 1 - dup to open-count + 0= IF close THEN + THEN + close +; + +: write ( adr len -- actual ) + tuck + 0 ?DO + dup c@ virtiodev SWAP virtio-serial-putchar + 1 + + LOOP + drop +; + +: read ( adr len -- actual ) + 0= IF drop 0 EXIT THEN + virtiodev virtio-serial-haschar 0= IF 0 swap c! -2 EXIT THEN + virtiodev virtio-serial-getchar swap c! 1 +; + +: setup-alias + " vsterm" find-alias 0= IF + " vsterm" get-node node>path set-alias + ELSE drop THEN +; +setup-alias + +\ Override serial methods to make term-io.fs happy +: serial-emit virtio-serial-term-emit ; +: serial-key? virtio-serial-term-key? ; +: serial-key virtio-serial-term-key ; + diff --git a/lib/libvirtio/Makefile b/lib/libvirtio/Makefile index bd6a1fa..87d9513 100644 --- a/lib/libvirtio/Makefile +++ b/lib/libvirtio/Makefile @@ -24,7 +24,7 @@ TARGET = ../libvirtio.a all: $(TARGET) -SRCS = virtio.c virtio-blk.c p9.c virtio-9p.c virtio-scsi.c virtio-net.c +SRCS = virtio.c virtio-blk.c p9.c virtio-9p.c virtio-scsi.c virtio-net.c virtio-serial.c OBJS = $(SRCS:%.c=%.o) diff --git a/lib/libvirtio/virtio-serial.c b/lib/libvirtio/virtio-serial.c new file mode 100644 index 0000000..ea56bef --- /dev/null +++ b/lib/libvirtio/virtio-serial.c @@ -0,0 +1,202 @@ +/****************************************************************************** + * Copyright (c) 2016 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +/* + * Virtio serial device definitions. + * See Virtio 1.0 - 5.3 Console Device, for details + */ +#include +#include +#include +#include +#include +#include "virtio.h" +#include "virtio-serial.h" +#include "virtio-internal.h" + +#define DRIVER_FEATURE_SUPPORT (VIRTIO_F_VERSION_1) +#define RX_ELEM_SIZE 4 +#define RX_NUM_ELEMS 128 + +#define RX_Q 0 +#define TX_Q 1 + +static struct vqs vq_rx; +static struct vqs vq_tx; +static uint16_t last_rx_idx; /* Last index in RX "used" ring */ + +int virtio_serial_init(struct virtio_device *dev) +{ + struct vring_avail *vq_avail; + int status = VIRTIO_STAT_ACKNOWLEDGE; + + /* Reset device */ + virtio_reset_device(dev); + + /* Acknowledge device. */ + virtio_set_status(dev, status); + + /* Tell HV that we know how to drive the device. */ + status |= VIRTIO_STAT_DRIVER; + virtio_set_status(dev, status); + + if (dev->is_modern) { + /* Negotiate features and sets FEATURES_OK if successful */ + if (virtio_negotiate_guest_features(dev, DRIVER_FEATURE_SUPPORT)) + goto dev_error; + + virtio_get_status(dev, &status); + } + + if (virtio_queue_init_vq(dev, &vq_rx, RX_Q)) + goto dev_error; + + /* Allocate memory for multiple receive buffers */ + vq_rx.buf_mem = SLOF_alloc_mem(RX_ELEM_SIZE * RX_NUM_ELEMS); + if (!vq_rx.buf_mem) { + printf("virtio-serial: Failed to allocate buffers!\n"); + goto dev_error; + } + + /* Prepare receive buffer queue */ + for (int i = 0; i < RX_NUM_ELEMS; i++) { + uint64_t addr = (uint64_t)vq_rx.buf_mem + i * RX_ELEM_SIZE; + + /* Descriptor for data: */ + virtio_fill_desc(&vq_rx.desc[i], dev->is_modern, addr, 1, VRING_DESC_F_WRITE, 0); + vq_rx.avail->ring[i] = virtio_cpu_to_modern16(dev, i); + } + vq_rx.avail->flags = virtio_cpu_to_modern16(dev, VRING_AVAIL_F_NO_INTERRUPT); + vq_rx.avail->idx = virtio_cpu_to_modern16(dev, RX_NUM_ELEMS); + sync(); + + last_rx_idx = virtio_modern16_to_cpu(dev, vq_rx.used->idx); + + if (virtio_queue_init_vq(dev, &vq_tx, TX_Q)) + goto dev_error; + + vq_avail = virtio_get_vring_avail(dev, TX_Q); + vq_avail->flags = virtio_cpu_to_modern16(dev, VRING_AVAIL_F_NO_INTERRUPT); + vq_avail->idx = 0; + + /* Tell HV that setup succeeded */ + status |= VIRTIO_STAT_DRIVER_OK; + virtio_set_status(dev, status); + + return 1; + dev_error: + printf("%s: failed\n", __func__); + status |= VIRTIO_STAT_FAILED; + virtio_set_status(dev, status); + return 0; +} + +void virtio_serial_shutdown(struct virtio_device *dev) +{ + /* Quiesce device */ + virtio_set_status(dev, VIRTIO_STAT_FAILED); + + /* Reset device */ + virtio_reset_device(dev); +} + +int virtio_serial_putchar(struct virtio_device *dev, char c) +{ + struct vring_desc *desc; + int id; + uint32_t vq_size, time; + struct vring_desc *vq_desc; /* Descriptor vring */ + struct vring_avail *vq_avail; /* "Available" vring */ + struct vring_used *vq_used; /* "Used" vring */ + volatile uint16_t *current_used_idx; + uint16_t last_used_idx, avail_idx; + + vq_size = virtio_get_qsize(dev, TX_Q); + vq_desc = virtio_get_vring_desc(dev, TX_Q); + vq_avail = virtio_get_vring_avail(dev, TX_Q); + vq_used = virtio_get_vring_used(dev, TX_Q); + + avail_idx = virtio_modern16_to_cpu(dev, vq_avail->idx); + + last_used_idx = vq_used->idx; + current_used_idx = &vq_used->idx; + + /* Determine descriptor index */ + id = (avail_idx * 1) % vq_size; + + /* Set up virtqueue descriptor for header */ + desc = &vq_desc[id]; + virtio_fill_desc(desc, dev->is_modern, (uint64_t)&c, 1, 0, 0); + + vq_avail->ring[avail_idx % vq_size] = virtio_cpu_to_modern16 (dev, id); + mb(); + vq_avail->idx = virtio_cpu_to_modern16(dev, avail_idx + 1); + + /* Tell HV that the queue is ready */ + virtio_queue_notify(dev, TX_Q); + + /* Wait for host to consume the descriptor */ + time = SLOF_GetTimer() + VIRTIO_TIMEOUT; + while (*current_used_idx == last_used_idx) { + // do something better + mb(); + if (time < SLOF_GetTimer()) { + printf("virtio_serial_putchar failed! \n"); + return 0; + } + } + + return 1; +} + +static uint16_t last_rx_idx; /* Last index in RX "used" ring */ + +char virtio_serial_getchar(struct virtio_device *dev) +{ + int id, idx; + char buf[RX_NUM_ELEMS] = {0}; + uint16_t avail_idx; + + idx = virtio_modern16_to_cpu(dev, vq_rx.used->idx); + if (last_rx_idx == idx) { + /* Nothing received yet */ + return 0; + } + + id = (virtio_modern32_to_cpu(dev, vq_rx.used->ring[last_rx_idx % vq_rx.size].id) + 1) + % vq_rx.size; + + /* Copy data to destination buffer */ + memcpy(buf, (void *)virtio_modern64_to_cpu(dev, vq_rx.desc[id - 1].addr), RX_ELEM_SIZE); + + /* Move indices to next entries */ + last_rx_idx = last_rx_idx + 1; + + avail_idx = virtio_modern16_to_cpu(dev, vq_rx.avail->idx); + vq_rx.avail->ring[avail_idx % vq_rx.size] = virtio_cpu_to_modern16(dev, id - 1); + sync(); + vq_rx.avail->idx = virtio_cpu_to_modern16(dev, avail_idx + 1); + sync(); + + /* Tell HV that RX queue entry is ready */ + virtio_queue_notify(dev, RX_Q); + + return buf[0]; +} + +int virtio_serial_haschar(struct virtio_device *dev) +{ + if (last_rx_idx == virtio_modern16_to_cpu(dev, vq_rx.used->idx)) + return 0; + else + return 1; +} diff --git a/lib/libvirtio/virtio-serial.h b/lib/libvirtio/virtio-serial.h new file mode 100644 index 0000000..8abfd16 --- /dev/null +++ b/lib/libvirtio/virtio-serial.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2016 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +/* + * Virtio serial device definitions. + * See Virtio 1.0 - 5.3 Console Device, for details + */ + +#ifndef _VIRTIO_SERIAL_H +#define _VIRTIO_SERIAL_H + +extern int virtio_serial_init(struct virtio_device *dev); +extern void virtio_serial_shutdown(struct virtio_device *dev); +extern int virtio_serial_putchar(struct virtio_device *dev, char c); +extern char virtio_serial_getchar(struct virtio_device *dev); +extern int virtio_serial_haschar(struct virtio_device *dev); + +#endif /* _VIRTIO_SERIAL_H */ + diff --git a/lib/libvirtio/virtio.code b/lib/libvirtio/virtio.code index 8eec8f0..5cfffcc 100644 --- a/lib/libvirtio/virtio.code +++ b/lib/libvirtio/virtio.code @@ -15,6 +15,7 @@ #include #include #include +#include /******** core virtio ********/ @@ -165,3 +166,35 @@ PRIM(virtio_X2d_net_X2d_write) TOS.n = virtionet_write(TOS.a, len); } MIRP + +/*********** virtio-serial ***********/ +// : virtio-serial-init ( dev -- false | true) +PRIM(virtio_X2d_serial_X2d_init) + void *dev = TOS.a; + TOS.u = virtio_serial_init(dev); +MIRP + +// : virtio-serial-shutdown ( dev -- ) +PRIM(virtio_X2d_serial_X2d_shutdown) + void *dev = TOS.a; POP; + virtio_serial_shutdown(dev); +MIRP + +// : virtio-serial-putchar ( dev char -- ) +PRIM(virtio_X2d_serial_X2d_putchar) + unsigned long c = TOS.n; POP; + void *dev = TOS.a; POP; + virtio_serial_putchar(dev, c); +MIRP + +// : virtio-serial-getchar ( dev -- char) +PRIM(virtio_X2d_serial_X2d_getchar) + void *dev = TOS.a; + TOS.n = virtio_serial_getchar(dev); +MIRP + +// : virtio-serial-haschar ( dev -- true | false) +PRIM(virtio_X2d_serial_X2d_haschar) + void *dev = TOS.a; + TOS.n = virtio_serial_haschar(dev); +MIRP diff --git a/lib/libvirtio/virtio.in b/lib/libvirtio/virtio.in index 195840e..d2b1641 100644 --- a/lib/libvirtio/virtio.in +++ b/lib/libvirtio/virtio.in @@ -33,3 +33,9 @@ cod(virtio-net-open) cod(virtio-net-close) cod(virtio-net-read) cod(virtio-net-write) + +cod(virtio-serial-init) +cod(virtio-serial-shutdown) +cod(virtio-serial-putchar) +cod(virtio-serial-getchar) +cod(virtio-serial-haschar)