From mboxrd@z Thu Jan 1 00:00:00 1970 From: Namhyung Kim Subject: [PATCH 6/7] qemu: Implement virtio-pstore device Date: Thu, 28 Jul 2016 00:08:30 +0900 Message-ID: <1469632111-23260-7-git-send-email-namhyung@kernel.org> References: <1469632111-23260-1-git-send-email-namhyung@kernel.org> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: LKML , Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , "Michael S. Tsirkin" , Anthony Liguori , Anton Vorontsov , Colin Cross , Kees Cook , Tony Luck , Steven Rostedt , Ingo Molnar , Minchan Kim To: kvm@vger.kernel.org, qemu-devel@nongnu.org, virtualization@lists.linux-foundation.org Return-path: In-Reply-To: <1469632111-23260-1-git-send-email-namhyung@kernel.org> Sender: linux-kernel-owner@vger.kernel.org List-Id: kvm.vger.kernel.org Add virtio pstore device to allow kernel log files saved on the host. It will save the log files on the directory given by pstore device option. $ qemu-system-x86_64 -device virtio-pstore,directory=3Ddir-xx ... (guest) # echo c > /proc/sysrq-trigger $ ls dir-xx dmesg-1.enc.z dmesg-2.enc.z The log files are usually compressed using zlib. Users can see the log messages directly on the host or on the guest (using pstore filesystem)= =2E The 'directory' property is required for virtio-pstore device to work. It also adds 'bufsize' and 'console' (boolean) properties. Cc: Paolo Bonzini Cc: Radim Kr=C4=8Dm=C3=A1=C5=99 Cc: "Michael S. Tsirkin" Cc: Anthony Liguori Cc: Anton Vorontsov Cc: Colin Cross Cc: Kees Cook Cc: Tony Luck Cc: Steven Rostedt Cc: Ingo Molnar Cc: Minchan Kim Cc: kvm@vger.kernel.org Cc: qemu-devel@nongnu.org Cc: virtualization@lists.linux-foundation.org Signed-off-by: Namhyung Kim --- hw/virtio/Makefile.objs | 2 +- hw/virtio/virtio-pci.c | 54 +++ hw/virtio/virtio-pci.h | 14 + hw/virtio/virtio-pstore.c | 477 +++++++++++++++++= ++++++++ include/hw/pci/pci.h | 1 + include/hw/virtio/virtio-pstore.h | 34 ++ include/standard-headers/linux/virtio_ids.h | 1 + include/standard-headers/linux/virtio_pstore.h | 80 +++++ qdev-monitor.c | 1 + 9 files changed, 663 insertions(+), 1 deletion(-) create mode 100644 hw/virtio/virtio-pstore.c create mode 100644 include/hw/virtio/virtio-pstore.h create mode 100644 include/standard-headers/linux/virtio_pstore.h diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs index 3e2b175..aae7082 100644 --- a/hw/virtio/Makefile.objs +++ b/hw/virtio/Makefile.objs @@ -4,4 +4,4 @@ common-obj-y +=3D virtio-bus.o common-obj-y +=3D virtio-mmio.o =20 obj-y +=3D virtio.o virtio-balloon.o=20 -obj-$(CONFIG_LINUX) +=3D vhost.o vhost-backend.o vhost-user.o +obj-$(CONFIG_LINUX) +=3D vhost.o vhost-backend.o vhost-user.o virtio-p= store.o diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index f0677b7..d99a405 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -2414,6 +2414,59 @@ static const TypeInfo virtio_host_pci_info =3D { }; #endif =20 +/* virtio-pstore-pci */ + +static void virtio_pstore_pci_realize(VirtIOPCIProxy *vpci_dev, Error = **errp) +{ + VirtIOPstorePCI *vps =3D VIRTIO_PSTORE_PCI(vpci_dev); + DeviceState *vdev =3D DEVICE(&vps->vdev); + Error *err =3D NULL; + + qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); + object_property_set_bool(OBJECT(vdev), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } +} + +static void virtio_pstore_pci_class_init(ObjectClass *klass, void *dat= a) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + VirtioPCIClass *k =3D VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k =3D PCI_DEVICE_CLASS(klass); + + k->realize =3D virtio_pstore_pci_realize; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + + pcidev_k->vendor_id =3D PCI_VENDOR_ID_REDHAT_QUMRANET; + pcidev_k->device_id =3D PCI_DEVICE_ID_VIRTIO_PSTORE; + pcidev_k->revision =3D VIRTIO_PCI_ABI_VERSION; + pcidev_k->class_id =3D PCI_CLASS_OTHERS; +} + +static void virtio_pstore_pci_instance_init(Object *obj) +{ + VirtIOPstorePCI *dev =3D VIRTIO_PSTORE_PCI(obj); + + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_PSTORE); + object_property_add_alias(obj, "directory", OBJECT(&dev->vdev), + "directory", &error_abort); + object_property_add_alias(obj, "bufsize", OBJECT(&dev->vdev), + "bufsize", &error_abort); + object_property_add_alias(obj, "console", OBJECT(&dev->vdev), + "console", &error_abort); +} + +static const TypeInfo virtio_pstore_pci_info =3D { + .name =3D TYPE_VIRTIO_PSTORE_PCI, + .parent =3D TYPE_VIRTIO_PCI, + .instance_size =3D sizeof(VirtIOPstorePCI), + .instance_init =3D virtio_pstore_pci_instance_init, + .class_init =3D virtio_pstore_pci_class_init, +}; + /* virtio-pci-bus */ =20 static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, @@ -2483,6 +2536,7 @@ static void virtio_pci_register_types(void) #ifdef CONFIG_VHOST_SCSI type_register_static(&vhost_scsi_pci_info); #endif + type_register_static(&virtio_pstore_pci_info); } =20 type_init(virtio_pci_register_types) diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index e4548c2..b4c039f 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -31,6 +31,7 @@ #ifdef CONFIG_VHOST_SCSI #include "hw/virtio/vhost-scsi.h" #endif +#include "hw/virtio/virtio-pstore.h" =20 typedef struct VirtIOPCIProxy VirtIOPCIProxy; typedef struct VirtIOBlkPCI VirtIOBlkPCI; @@ -44,6 +45,7 @@ typedef struct VirtIOInputPCI VirtIOInputPCI; typedef struct VirtIOInputHIDPCI VirtIOInputHIDPCI; typedef struct VirtIOInputHostPCI VirtIOInputHostPCI; typedef struct VirtIOGPUPCI VirtIOGPUPCI; +typedef struct VirtIOPstorePCI VirtIOPstorePCI; =20 /* virtio-pci-bus */ =20 @@ -311,6 +313,18 @@ struct VirtIOGPUPCI { VirtIOGPU vdev; }; =20 +/* + * virtio-pstore-pci: This extends VirtioPCIProxy. + */ +#define TYPE_VIRTIO_PSTORE_PCI "virtio-pstore-pci" +#define VIRTIO_PSTORE_PCI(obj) \ + OBJECT_CHECK(VirtIOPstorePCI, (obj), TYPE_VIRTIO_PSTORE_PCI) + +struct VirtIOPstorePCI { + VirtIOPCIProxy parent_obj; + VirtIOPstore vdev; +}; + /* Virtio ABI version, if we increment this, we break the guest driver= =2E */ #define VIRTIO_PCI_ABI_VERSION 0 =20 diff --git a/hw/virtio/virtio-pstore.c b/hw/virtio/virtio-pstore.c new file mode 100644 index 0000000..2ca7786 --- /dev/null +++ b/hw/virtio/virtio-pstore.c @@ -0,0 +1,477 @@ +/* + * Virtio Pstore Device + * + * Copyright (C) 2016 LG Electronics + * + * Authors: + * Namhyung Kim + * + * This work is licensed under the terms of the GNU GPL, version 2. S= ee + * the COPYING file in the top-level directory. + * + */ + +#include + +#include "qemu/osdep.h" +#include "qemu/iov.h" +#include "qemu-common.h" +#include "qemu/cutils.h" +#include "qemu/error-report.h" +#include "sysemu/kvm.h" +#include "qapi/visitor.h" +#include "qapi-event.h" +#include "trace.h" + +#include "hw/virtio/virtio.h" +#include "hw/virtio/virtio-bus.h" +#include "hw/virtio/virtio-access.h" +#include "hw/virtio/virtio-pstore.h" + + +static void virtio_pstore_to_filename(VirtIOPstore *s, char *buf, size= _t sz, + struct virtio_pstore_req *req) +{ + const char *basename; + unsigned long long id =3D 0; + unsigned int flags =3D le32_to_cpu(req->flags); + + switch (le16_to_cpu(req->type)) { + case VIRTIO_PSTORE_TYPE_DMESG: + basename =3D "dmesg"; + id =3D s->id++; + break; + case VIRTIO_PSTORE_TYPE_CONSOLE: + basename =3D "console"; + if (s->console_id) { + id =3D s->console_id; + } else { + id =3D s->console_id =3D s->id++; + } + break; + default: + basename =3D "unknown"; + break; + } + + snprintf(buf, sz, "%s/%s-%llu%s", s->directory, basename, id, + flags & VIRTIO_PSTORE_FL_COMPRESSED ? ".enc.z" : ""); +} + +static void virtio_pstore_from_filename(VirtIOPstore *s, char *name, + char *buf, size_t sz, + struct virtio_pstore_fileinfo = *info) +{ + snprintf(buf, sz, "%s/%s", s->directory, name); + + if (g_str_has_prefix(name, "dmesg-")) { + info->type =3D VIRTIO_PSTORE_TYPE_DMESG; + name +=3D strlen("dmesg-"); + } else if (g_str_has_prefix(name, "console-")) { + info->type =3D VIRTIO_PSTORE_TYPE_CONSOLE; + name +=3D strlen("console-"); + } else if (g_str_has_prefix(name, "unknown-")) { + info->type =3D VIRTIO_PSTORE_TYPE_UNKNOWN; + name +=3D strlen("unknown-"); + } + + qemu_strtoull(name, NULL, 0, &info->id); + + info->flags =3D 0; + if (g_str_has_suffix(name, ".enc.z")) { + info->flags |=3D VIRTIO_PSTORE_FL_COMPRESSED; + } +} + +static ssize_t virtio_pstore_do_open(VirtIOPstore *s) +{ + s->dirp =3D opendir(s->directory); + if (s->dirp =3D=3D NULL) { + return -1; + } + + return 0; +} + +static ssize_t virtio_pstore_do_read(VirtIOPstore *s, struct iovec *in= _sg, + unsigned int in_num, + struct virtio_pstore_res *res) +{ + char path[PATH_MAX]; + int fd; + ssize_t len; + struct stat stbuf; + struct dirent *dent; + int sg_num =3D in_num; + struct iovec sg[sg_num]; + struct virtio_pstore_fileinfo info; + size_t offset =3D sizeof(*res) + sizeof(info); + + if (s->dirp =3D=3D NULL) { + return -1; + } + + dent =3D readdir(s->dirp); + while (dent) { + if (dent->d_name[0] !=3D '.') { + break; + } + dent =3D readdir(s->dirp); + } + + if (dent =3D=3D NULL) { + return 0; + } + + /* skip res and fileinfo */ + sg_num =3D iov_copy(sg, sg_num, in_sg, in_num, offset, + iov_size(in_sg, in_num) - offset); + + virtio_pstore_from_filename(s, dent->d_name, path, sizeof(path), &= info); + fd =3D open(path, O_RDONLY); + if (fd < 0) { + error_report("cannot open %s", path); + return -1; + } + + if (fstat(fd, &stbuf) < 0) { + len =3D -1; + goto out; + } + + len =3D readv(fd, sg, sg_num); + if (len < 0) { + if (errno =3D=3D EAGAIN) { + len =3D 0; + } + goto out; + } + + info.id =3D cpu_to_le64(info.id); + info.type =3D cpu_to_le16(info.type); + info.flags =3D cpu_to_le32(info.flags); + info.len =3D cpu_to_le32(len); + info.time_sec =3D cpu_to_le64(stbuf.st_ctim.tv_sec); + info.time_nsec =3D cpu_to_le32(stbuf.st_ctim.tv_nsec); + + iov_from_buf(in_sg, in_num, sizeof(*res), &info, sizeof(info)); + len +=3D sizeof(info); + + out: + close(fd); + return len; +} + +static ssize_t virtio_pstore_do_write(VirtIOPstore *s, struct iovec *o= ut_sg, + unsigned int out_num, + struct virtio_pstore_req *req) +{ + char path[PATH_MAX]; + int fd; + ssize_t len; + unsigned short type; + int flags =3D O_WRONLY | O_CREAT; + + /* we already consume the req */ + iov_discard_front(&out_sg, &out_num, sizeof(*req)); + + virtio_pstore_to_filename(s, path, sizeof(path), req); + + type =3D le16_to_cpu(req->type); + + if (type =3D=3D VIRTIO_PSTORE_TYPE_DMESG) { + flags |=3D O_TRUNC; + } else if (type =3D=3D VIRTIO_PSTORE_TYPE_CONSOLE) { + flags |=3D O_APPEND; + } + + fd =3D open(path, flags, 0644); + if (fd < 0) { + error_report("cannot open %s", path); + return -1; + } + len =3D writev(fd, out_sg, out_num); + close(fd); + + return len; +} + +static ssize_t virtio_pstore_do_close(VirtIOPstore *s) +{ + if (s->dirp =3D=3D NULL) { + return 0; + } + + closedir(s->dirp); + s->dirp =3D NULL; + + return 0; +} + +static ssize_t virtio_pstore_do_erase(VirtIOPstore *s, + struct virtio_pstore_req *req) +{ + char path[PATH_MAX]; + + virtio_pstore_to_filename(s, path, sizeof(path), req); + + return unlink(path); +} + +static void virtio_pstore_handle_io(VirtIODevice *vdev, VirtQueue *vq) +{ + VirtIOPstore *s =3D VIRTIO_PSTORE(vdev); + VirtQueueElement *elem; + struct virtio_pstore_req req; + struct virtio_pstore_res res; + ssize_t len =3D 0; + int ret; + + for (;;) { + elem =3D virtqueue_pop(vq, sizeof(VirtQueueElement)); + if (!elem) { + return; + } + + if (elem->out_num < 1 || elem->in_num < 1) { + error_report("request or response buffer is missing"); + exit(1); + } + + len =3D iov_to_buf(elem->out_sg, elem->out_num, 0, &req, sizeo= f(req)); + if (len !=3D (ssize_t)sizeof(req)) { + error_report("invalid request size: %ld", (long)len); + exit(1); + } + res.cmd =3D req.cmd; + res.type =3D req.type; + + switch (le16_to_cpu(req.cmd)) { + case VIRTIO_PSTORE_CMD_OPEN: + ret =3D virtio_pstore_do_open(s); + break; + case VIRTIO_PSTORE_CMD_READ: + ret =3D virtio_pstore_do_read(s, elem->in_sg, elem->in_num= , &res); + if (ret > 0) { + len =3D ret; + ret =3D 0; + } + break; + case VIRTIO_PSTORE_CMD_WRITE: + ret =3D virtio_pstore_do_write(s, elem->out_sg, elem->out_= num, &req); + break; + case VIRTIO_PSTORE_CMD_CLOSE: + ret =3D virtio_pstore_do_close(s); + break; + case VIRTIO_PSTORE_CMD_ERASE: + ret =3D virtio_pstore_do_erase(s, &req); + break; + default: + ret =3D -1; + break; + } + + res.ret =3D ret; + + iov_from_buf(elem->in_sg, elem->in_num, 0, &res, sizeof(res)); + virtqueue_push(vq, elem, sizeof(res) + len); + + virtio_notify(vdev, vq); + g_free(elem); + + if (ret < 0) { + return; + } + } +} + +static void virtio_pstore_device_realize(DeviceState *dev, Error **err= p) +{ + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); + VirtIOPstore *s =3D VIRTIO_PSTORE(dev); + + virtio_init(vdev, "virtio-pstore", VIRTIO_ID_PSTORE, + sizeof(struct virtio_pstore_config)); + + s->id =3D 1; + s->console_id =3D 0; + + s->vq[0] =3D virtio_add_queue(vdev, 128, virtio_pstore_handle_io); + s->vq[1] =3D virtio_add_queue(vdev, 128, virtio_pstore_handle_io); +} + +static void virtio_pstore_device_unrealize(DeviceState *dev, Error **e= rrp) +{ + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); + + virtio_cleanup(vdev); +} + +static void virtio_pstore_get_config(VirtIODevice *vdev, uint8_t *conf= ig_data) +{ + VirtIOPstore *dev =3D VIRTIO_PSTORE(vdev); + struct virtio_pstore_config config; + + config.bufsize =3D cpu_to_le32(dev->bufsize); + if (dev->console) { + config.flags |=3D cpu_to_le32(VIRTIO_PSTORE_CONFIG_FL_CONSOLE)= ; + } + + memcpy(config_data, &config, sizeof(struct virtio_pstore_config)); +} + +static void virtio_pstore_set_config(VirtIODevice *vdev, + const uint8_t *config_data) +{ + VirtIOPstore *dev =3D VIRTIO_PSTORE(vdev); + struct virtio_pstore_config config; + + memcpy(&config, config_data, sizeof(struct virtio_pstore_config)); + + dev->bufsize =3D le32_to_cpu(config.bufsize); +} + +static uint64_t get_features(VirtIODevice *vdev, uint64_t f, Error **e= rrp) +{ + return f; +} + +static void pstore_get_directory(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + VirtIOPstore *s =3D opaque; + + visit_type_str(v, name, &s->directory, errp); +} + +static void pstore_set_directory(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + VirtIOPstore *s =3D opaque; + Error *local_err =3D NULL; + char *value; + + visit_type_str(v, name, &value, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + g_free(s->directory); + s->directory =3D value; +} + +static void pstore_release_directory(Object *obj, const char *name, + void *opaque) +{ + VirtIOPstore *s =3D opaque; + + g_free(s->directory); + s->directory =3D NULL; +} + +static void pstore_get_bufsize(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + VirtIOPstore *s =3D opaque; + uint64_t value =3D s->bufsize; + + visit_type_size(v, name, &value, errp); +} + +static void pstore_set_bufsize(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + VirtIOPstore *s =3D opaque; + Error *error =3D NULL; + uint64_t value; + + visit_type_size(v, name, &value, &error); + if (error) { + error_propagate(errp, error); + return; + } + + if (value < 4096) { + error_report("Warning: too small buffer size: %"PRIu64, value)= ; + } + + s->bufsize =3D value; +} + +static void pstore_get_console(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + VirtIOPstore *s =3D opaque; + bool value =3D s->console; + + visit_type_bool(v, name, &value, errp); +} + +static void pstore_set_console(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + VirtIOPstore *s =3D opaque; + Error *error =3D NULL; + bool value; + + visit_type_bool(v, name, &value, &error); + if (error) { + error_propagate(errp, error); + return; + } + + s->console =3D value; +} + +static Property virtio_pstore_properties[] =3D { + DEFINE_PROP_END_OF_LIST(), +}; + +static void virtio_pstore_instance_init(Object *obj) +{ + VirtIOPstore *s =3D VIRTIO_PSTORE(obj); + + object_property_add(obj, "directory", "str", + pstore_get_directory, pstore_set_directory, + pstore_release_directory, s, NULL); + object_property_add(obj, "bufsize", "size", + pstore_get_bufsize, pstore_set_bufsize, NULL, = s, NULL); + object_property_add(obj, "console", "bool", + pstore_get_console, pstore_set_console, NULL, = s, NULL); +} + +static void virtio_pstore_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(klass); + + dc->props =3D virtio_pstore_properties; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + vdc->realize =3D virtio_pstore_device_realize; + vdc->unrealize =3D virtio_pstore_device_unrealize; + vdc->get_config =3D virtio_pstore_get_config; + vdc->set_config =3D virtio_pstore_set_config; + vdc->get_features =3D get_features; +} + +static const TypeInfo virtio_pstore_info =3D { + .name =3D TYPE_VIRTIO_PSTORE, + .parent =3D TYPE_VIRTIO_DEVICE, + .instance_size =3D sizeof(VirtIOPstore), + .instance_init =3D virtio_pstore_instance_init, + .class_init =3D virtio_pstore_class_init, +}; + +static void virtio_register_types(void) +{ + type_register_static(&virtio_pstore_info); +} + +type_init(virtio_register_types) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 74d797d..000e1e9 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -79,6 +79,7 @@ #define PCI_DEVICE_ID_VIRTIO_SCSI 0x1004 #define PCI_DEVICE_ID_VIRTIO_RNG 0x1005 #define PCI_DEVICE_ID_VIRTIO_9P 0x1009 +#define PCI_DEVICE_ID_VIRTIO_PSTORE 0x100a =20 #define PCI_VENDOR_ID_REDHAT 0x1b36 #define PCI_DEVICE_ID_REDHAT_BRIDGE 0x0001 diff --git a/include/hw/virtio/virtio-pstore.h b/include/hw/virtio/virt= io-pstore.h new file mode 100644 index 0000000..d188a48 --- /dev/null +++ b/include/hw/virtio/virtio-pstore.h @@ -0,0 +1,34 @@ +/* + * Virtio Pstore Support + * + * Authors: + * Namhyung Kim + * + * This work is licensed under the terms of the GNU GPL, version 2. S= ee + * the COPYING file in the top-level directory. + * + */ + +#ifndef _QEMU_VIRTIO_PSTORE_H +#define _QEMU_VIRTIO_PSTORE_H + +#include "standard-headers/linux/virtio_pstore.h" +#include "hw/virtio/virtio.h" +#include "hw/pci/pci.h" + +#define TYPE_VIRTIO_PSTORE "virtio-pstore-device" +#define VIRTIO_PSTORE(obj) \ + OBJECT_CHECK(VirtIOPstore, (obj), TYPE_VIRTIO_PSTORE) + +typedef struct VirtIOPstore { + VirtIODevice parent_obj; + VirtQueue *vq[2]; + char *directory; + uint64_t id; + uint64_t console_id; + DIR *dirp; + uint64_t bufsize; + bool console; +} VirtIOPstore; + +#endif diff --git a/include/standard-headers/linux/virtio_ids.h b/include/stan= dard-headers/linux/virtio_ids.h index 77925f5..c72a9ab 100644 --- a/include/standard-headers/linux/virtio_ids.h +++ b/include/standard-headers/linux/virtio_ids.h @@ -41,5 +41,6 @@ #define VIRTIO_ID_CAIF 12 /* Virtio caif */ #define VIRTIO_ID_GPU 16 /* virtio GPU */ #define VIRTIO_ID_INPUT 18 /* virtio input */ +#define VIRTIO_ID_PSTORE 22 /* virtio pstore */ =20 #endif /* _LINUX_VIRTIO_IDS_H */ diff --git a/include/standard-headers/linux/virtio_pstore.h b/include/s= tandard-headers/linux/virtio_pstore.h new file mode 100644 index 0000000..b893d15 --- /dev/null +++ b/include/standard-headers/linux/virtio_pstore.h @@ -0,0 +1,80 @@ +#ifndef _LINUX_VIRTIO_PSTORE_H +#define _LINUX_VIRTIO_PSTORE_H +/* This header is BSD licensed so anyone can use the definitions to im= plement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyrigh= t + * notice, this list of conditions and the following disclaimer in = the + * documentation and/or other materials provided with the distribut= ion. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this sof= tware + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS= ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, T= HE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR = PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQ= UENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE G= OODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTIO= N) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,= STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN A= NY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY= OF + * SUCH DAMAGE. */ +#include "standard-headers/linux/types.h" +#include "standard-headers/linux/virtio_types.h" +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_config.h" + +#define VIRTIO_PSTORE_CMD_NULL 0 +#define VIRTIO_PSTORE_CMD_OPEN 1 +#define VIRTIO_PSTORE_CMD_READ 2 +#define VIRTIO_PSTORE_CMD_WRITE 3 +#define VIRTIO_PSTORE_CMD_ERASE 4 +#define VIRTIO_PSTORE_CMD_CLOSE 5 + +#define VIRTIO_PSTORE_TYPE_UNKNOWN 0 +#define VIRTIO_PSTORE_TYPE_DMESG 1 +#define VIRTIO_PSTORE_TYPE_CONSOLE 2 + +#define VIRTIO_PSTORE_FL_COMPRESSED 1 + +#define VIRTIO_PSTORE_CONFIG_FL_CONSOLE (1 << 0) + +struct virtio_pstore_req { + __virtio16 cmd; + __virtio16 type; + __virtio32 flags; + __virtio64 id; + __virtio32 count; + __virtio32 reserved; +}; + +struct virtio_pstore_res { + __virtio16 cmd; + __virtio16 type; + __virtio32 ret; +}; + +struct virtio_pstore_fileinfo { + __virtio64 id; + __virtio32 count; + __virtio16 type; + __virtio16 unused; + __virtio32 flags; + __virtio32 len; + __virtio64 time_sec; + __virtio32 time_nsec; + __virtio32 reserved; +}; + +struct virtio_pstore_config { + __virtio32 bufsize; + __virtio32 flags; +}; + +#endif /* _LINUX_VIRTIO_PSTORE_H */ diff --git a/qdev-monitor.c b/qdev-monitor.c index e19617f..e1df5a9 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -73,6 +73,7 @@ static const QDevAlias qdev_alias_table[] =3D { { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_ALL & ~QEMU_ARCH= _S390X }, { "virtio-tablet-ccw", "virtio-tablet", QEMU_ARCH_S390X }, { "virtio-tablet-pci", "virtio-tablet", QEMU_ARCH_ALL & ~QEMU_ARCH= _S390X }, + { "virtio-pstore-pci", "virtio-pstore" }, { } }; =20 --=20 2.8.0