Re: [Qemu-devel] [PATCH 6/7] s390: sclp ascii console support
On Tue, Jul 24, 2012 at 7:37 AM, Christian Borntraeger borntrae...@de.ibm.com wrote: From: Heinz Graalfs graa...@linux.vnet.ibm.com This code adds console support by implementing SCLP's ASCII Console Data event. This is the same console as LPARs ASCII console or z/VMs sysascii. The console can be specified manually with something like -chardev stdio,id=charconsole0 -device sclpconsole,chardev=charconsole0,id=console0 Newer kernels will autodetect that console and prefer that over virtio console. When data is received from the character layer it creates a service interrupt to trigger a Read Event Data command from the guest that will pick up the received character byte-stream. When characters are echo'ed by the linux guest a Write Event Data occurs which is forwarded by the Event Facility to the console that supports a corresponding mask value. Console resizing is not supported. The character layer byte-stream is buffered using a fixed size iov buffer. Signed-off-by: Heinz Graalfs graa...@linux.vnet.ibm.com Signed-off-by: Christian Borntraeger borntrae...@de.ibm.com --- hw/s390x/Makefile.objs |2 +- hw/s390x/sclpconsole.c | 323 2 files changed, 324 insertions(+), 1 deletions(-) create mode 100644 hw/s390x/sclpconsole.c diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index ed4e61a..096dfcd 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -3,4 +3,4 @@ obj-y = s390-virtio-bus.o s390-virtio.o obj-y := $(addprefix ../,$(obj-y)) obj-y += sclp.o obj-y += event-facility.o -obj-y += sclpquiesce.o +obj-y += sclpquiesce.o sclpconsole.o diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c new file mode 100644 index 000..9a57032 --- /dev/null +++ b/hw/s390x/sclpconsole.c @@ -0,0 +1,323 @@ +/* + * SCLP event type + *Ascii Console Data (VT220 Console) + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Heinz Graalfs graa...@de.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#include hw/qdev.h +#include qemu-thread.h + +#include sclp.h +#include event-facility.h + +typedef struct ASCIIConsoleData { +EventBufferHeader ebh; +char data[0]; +} QEMU_PACKED ASCIIConsoleData; + +qemu_irq sclp_read_vt220; This should go into SCLPConsole. + +/* max size for ASCII data in 4K SCCB page */ +#define SIZE_BUFFER_VT220 4080 + +typedef struct SCLPConsole { +SCLPEvent event; +CharDriverState *chr; +/* io vector */ +uint8_t *iov; /* iov buffer pointer */ +uint8_t *iov_sclp; /* pointer to SCLP read offset */ +uint8_t *iov_bs;/* pointer byte stream read offset */ +uint32_t iov_data_len; /* length of byte stream in buffer */ +uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */ +} SCLPConsole; + +/* character layer call-back functions */ + +/* Return number of bytes that fit into iov buffer */ +static int chr_can_read(void *opaque) +{ +int can_read; +SCLPConsole *scon = opaque; + +qemu_mutex_lock(scon-event.lock); +can_read = SIZE_BUFFER_VT220 - scon-iov_data_len; +qemu_mutex_unlock(scon-event.lock); + +return can_read; +} + +/* Receive n bytes from character layer, save in iov buffer, + * and set event pending */ +static void receive_from_chr_layer(void *opaque, const uint8_t *buf, int size) +{ +SCLPConsole *scon = opaque; + +assert(scon-iov); + +qemu_mutex_lock(scon-event.lock); + +/* if new data do not fit into current buffer */ +if (scon-iov_data_len + size SIZE_BUFFER_VT220) { +/* character layer sent more than allowed */ +qemu_mutex_unlock(scon-event.lock); +return; +} +/* put byte-stream from character layer into buffer */ +memcpy(scon-iov_bs, buf, size); +scon-iov_data_len += size; +scon-iov_sclp_rest += size; +scon-iov_bs += size; +scon-event.event_pending = true; + +qemu_mutex_unlock(scon-event.lock); +} + +/* Send data from a char device over to the guest */ +static void chr_read(void *opaque, const uint8_t *buf, int size) +{ +assert(opaque); + I'd convert the opaque to SCLPConsole here and use that for receive_from_chr_layer() instead of opaque. +receive_from_chr_layer(opaque, buf, size); +/* trigger SCLP read operation */ +qemu_irq_raise(sclp_read_vt220); +} + +static void chr_event(void *opaque, int event) +{ +SCLPConsole *scon = opaque; + +switch (event) { +case CHR_EVENT_OPENED: +if (!scon-iov) { +scon-iov = g_malloc0(SIZE_BUFFER_VT220); +scon-iov_sclp = scon-iov; +
[Qemu-devel] [PATCH 6/7] s390: sclp ascii console support
From: Heinz Graalfs graa...@linux.vnet.ibm.com This code adds console support by implementing SCLP's ASCII Console Data event. This is the same console as LPARs ASCII console or z/VMs sysascii. The console can be specified manually with something like -chardev stdio,id=charconsole0 -device sclpconsole,chardev=charconsole0,id=console0 Newer kernels will autodetect that console and prefer that over virtio console. When data is received from the character layer it creates a service interrupt to trigger a Read Event Data command from the guest that will pick up the received character byte-stream. When characters are echo'ed by the linux guest a Write Event Data occurs which is forwarded by the Event Facility to the console that supports a corresponding mask value. Console resizing is not supported. The character layer byte-stream is buffered using a fixed size iov buffer. Signed-off-by: Heinz Graalfs graa...@linux.vnet.ibm.com Signed-off-by: Christian Borntraeger borntrae...@de.ibm.com --- hw/s390x/Makefile.objs |2 +- hw/s390x/sclpconsole.c | 323 2 files changed, 324 insertions(+), 1 deletions(-) create mode 100644 hw/s390x/sclpconsole.c diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index ed4e61a..096dfcd 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -3,4 +3,4 @@ obj-y = s390-virtio-bus.o s390-virtio.o obj-y := $(addprefix ../,$(obj-y)) obj-y += sclp.o obj-y += event-facility.o -obj-y += sclpquiesce.o +obj-y += sclpquiesce.o sclpconsole.o diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c new file mode 100644 index 000..9a57032 --- /dev/null +++ b/hw/s390x/sclpconsole.c @@ -0,0 +1,323 @@ +/* + * SCLP event type + *Ascii Console Data (VT220 Console) + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Heinz Graalfs graa...@de.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ + +#include hw/qdev.h +#include qemu-thread.h + +#include sclp.h +#include event-facility.h + +typedef struct ASCIIConsoleData { +EventBufferHeader ebh; +char data[0]; +} QEMU_PACKED ASCIIConsoleData; + +qemu_irq sclp_read_vt220; + +/* max size for ASCII data in 4K SCCB page */ +#define SIZE_BUFFER_VT220 4080 + +typedef struct SCLPConsole { +SCLPEvent event; +CharDriverState *chr; +/* io vector */ +uint8_t *iov; /* iov buffer pointer */ +uint8_t *iov_sclp; /* pointer to SCLP read offset */ +uint8_t *iov_bs;/* pointer byte stream read offset */ +uint32_t iov_data_len; /* length of byte stream in buffer */ +uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */ +} SCLPConsole; + +/* character layer call-back functions */ + +/* Return number of bytes that fit into iov buffer */ +static int chr_can_read(void *opaque) +{ +int can_read; +SCLPConsole *scon = opaque; + +qemu_mutex_lock(scon-event.lock); +can_read = SIZE_BUFFER_VT220 - scon-iov_data_len; +qemu_mutex_unlock(scon-event.lock); + +return can_read; +} + +/* Receive n bytes from character layer, save in iov buffer, + * and set event pending */ +static void receive_from_chr_layer(void *opaque, const uint8_t *buf, int size) +{ +SCLPConsole *scon = opaque; + +assert(scon-iov); + +qemu_mutex_lock(scon-event.lock); + +/* if new data do not fit into current buffer */ +if (scon-iov_data_len + size SIZE_BUFFER_VT220) { +/* character layer sent more than allowed */ +qemu_mutex_unlock(scon-event.lock); +return; +} +/* put byte-stream from character layer into buffer */ +memcpy(scon-iov_bs, buf, size); +scon-iov_data_len += size; +scon-iov_sclp_rest += size; +scon-iov_bs += size; +scon-event.event_pending = true; + +qemu_mutex_unlock(scon-event.lock); +} + +/* Send data from a char device over to the guest */ +static void chr_read(void *opaque, const uint8_t *buf, int size) +{ +assert(opaque); + +receive_from_chr_layer(opaque, buf, size); +/* trigger SCLP read operation */ +qemu_irq_raise(sclp_read_vt220); +} + +static void chr_event(void *opaque, int event) +{ +SCLPConsole *scon = opaque; + +switch (event) { +case CHR_EVENT_OPENED: +if (!scon-iov) { +scon-iov = g_malloc0(SIZE_BUFFER_VT220); +scon-iov_sclp = scon-iov; +scon-iov_bs = scon-iov; +scon-iov_data_len = 0; +scon-iov_sclp_rest = 0; +} +break; +case CHR_EVENT_CLOSED: +if (scon-iov) { +g_free(scon-iov); +scon-iov = NULL; +} +break; +} +} + +/* functions to be called by event facility */ + +static int event_type(void) +{ +return