On Mon, 2026-09-28 at 09:32 -0400, Jason J. Herne wrote:
> 
> 
> On 9/28/26 5:08 AM, Maximilian Immanuel Brandtner wrote:
> > Add a tty code to indicate a resize frame. The body contains two
> > big
> > endian 16-bit integers rows and columns.
> > 
> > After reset, the guest must be informed of the terminal size again.
> > A
> > chardev that doesn't report its size yields 0x0, which shouldn't
> > replace
> > the guest's default.
> > 
> > Signed-off-by: Maximilian Immanuel Brandtner <[email protected]>
> > ---
> > Changelog:
> > v2:
> > - Use packed struct and named event type codes for resize frames
> > - Trigger initial resize event in console_reset() instead of
> >    console_init(), skip when chardev reports no size
> > - Reset event_pending after resize event
> > 
> > Requires the following pre-req:
> >      [PATCH v7 00/12] virtio-console: notify about the terminal
> > size
> >     
> > (https://lore.kernel.org/qemu-devel/20260609-console-resize-v7-0-0c
> > [email protected]/)
> > 
> > Testing:
> > - Tested on QEMU: commit 38879a667f with the following patches
> > applied:
> >      [PATCH v7 00/12] virtio-console: notify about the terminal
> > size
> > - Tested on linux-next (commit c1f49dea2b8f) with the following
> > patches
> >    applied:
> >      [PATCH 0/2] s390/sclp: Resize for sclp-vt220 console
> > ---
> >   hw/char/sclpconsole.c | 92 +++++++++++++++++++++++++++++++++++++-
> > -----
> >   1 file changed, 80 insertions(+), 12 deletions(-)
> > 
> > diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
> > index 179d12745c..12033e1e46 100644
> > --- a/hw/char/sclpconsole.c
> > +++ b/hw/char/sclpconsole.c
> > @@ -33,6 +33,9 @@ typedef struct ASCIIConsoleData {
> >   /* max size for ASCII data in 4K SCCB page */
> >   #define SIZE_BUFFER_VT220 4080
> >   
> > +#define SCLP_CONSOLE_EVENT_TYPE_DATA 0x00
> > +#define SCLP_CONSOLE_EVENT_TYPE_RESIZE 0x08
> > +
> >   struct SCLPConsole {
> >       SCLPEvent event;
> >       CharFrontend chr;
> > @@ -42,6 +45,8 @@ struct SCLPConsole {
> >       uint32_t iov_data_len;  /* length of byte stream in
> > buffer             */
> >       uint32_t iov_sclp_rest; /* length of byte stream not read via
> > SCLP     */
> >       bool notify;            /* qemu_notify_event() req'd if
> > true           */
> > +    bool resize;
> > +    bool resize_init;
> >   };
> >   typedef struct SCLPConsole SCLPConsole;
> >   
> > @@ -49,6 +54,12 @@ typedef struct SCLPConsole SCLPConsole;
> >   DECLARE_INSTANCE_CHECKER(SCLPConsole, SCLP_CONSOLE,
> >                            TYPE_SCLP_CONSOLE)
> >   
> > +typedef struct SCLPConsoleResizeData {
> > +    uint8_t type;
> > +    uint16_t rows;
> > +    uint16_t cols;
> > +} QEMU_PACKED SCLPConsoleResizeData;
> > +
> >   /* character layer call-back functions */
> >   
> >   /* Return number of bytes that fit into iov buffer */
> > @@ -81,6 +92,29 @@ static void chr_read(void *opaque, const uint8_t
> > *buf, int size)
> >       sclp_service_interrupt(0);
> >   }
> >   
> > +static void chr_event(void *opaque, QEMUChrEvent event)
> > +{
> > +    SCLPConsole *scon = opaque;
> > +
> > +    assert(scon);
> > +
> > +    switch (event) {
> > +    case CHR_EVENT_RESIZE:
> > +    case CHR_EVENT_MUX_IN:
> > +        scon->resize = true;
> > +        scon->resize_init = false;
> > +        scon->event.event_pending = true;
> > +        sclp_service_interrupt(0);
> > +        break;
> > +    case CHR_EVENT_BREAK:
> > +    case CHR_EVENT_OPENED:
> > +    case CHR_EVENT_MUX_OUT:
> > +    case CHR_EVENT_CLOSED:
> > +        /* ignore */
> > +        break;
> > +    }
> > +}
> > +
> >   /* functions to be called by event facility */
> >   
> >   static bool can_handle_event(uint8_t type)
> > @@ -104,10 +138,37 @@ static sccb_mask_t receive_mask(void)
> >   static void get_console_data(SCLPEvent *event, uint8_t *buf,
> > size_t *size,
> >                                int avail)
> >   {
> > +    SCLPConsoleResizeData resize_data;
> >       SCLPConsole *cons = SCLP_CONSOLE(event);
> > +    uint16_t rows, cols;
> > +
> > +    if (cons->resize) {
> > +        if (avail < sizeof(resize_data)) {
> > +            *size = 0;
> > +            return;
> > +        }
> >   
> > -    /* first byte is hex 0 saying an ascii string follows */
> > -    *buf++ = '\0';
> > +        qemu_chr_fe_get_winsize(&cons->chr, &cols, &rows);
> > +
> > +        if (cons->resize_init && cols == 0 && rows == 0) {
> > +            *size = 0;
> > +        } else {
> > +            resize_data.type = SCLP_CONSOLE_EVENT_TYPE_RESIZE;
> > +            resize_data.rows = cpu_to_be16(rows);
> > +            resize_data.cols = cpu_to_be16(cols);
> > +
> > +            memcpy(buf, &resize_data, sizeof(resize_data));
> > +            *size = sizeof(resize_data);
> > +        }
> > +
> > +        cons->resize = false;
> > +        cons->resize_init = false;
> > +        event->event_pending = cons->iov_sclp_rest != 0;
> > +
> > +        return;
> > +    }
> > +
> > +    *buf++ = SCLP_CONSOLE_EVENT_TYPE_DATA;
> >       avail--;
> >       /* if all data fit into provided SCLP buffer */
> >       if (avail >= cons->iov_sclp_rest) {
> > @@ -150,6 +211,9 @@ static int read_event_data(SCLPEvent *event,
> > EventBufferHeader *evt_buf_hdr,
> >       to = (uint8_t *)&acd->data;
> >       avail = *slen - sizeof(ASCIIConsoleData);
> >       get_console_data(event, to, &src_len, avail);
> > +    if (src_len == 0) {
> > +        return 0;
> > +    }
> >       acd->ebh.length = cpu_to_be16(sizeof(ASCIIConsoleData) +
> > src_len);
> >       acd->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
> > @@ -233,22 +297,26 @@ static int console_init(SCLPEvent *event)
> >       }
> >       console_available = true;
> >       qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
> > -                             chr_read, NULL, NULL, scon, NULL,
> > true);
> > +                             chr_read, chr_event, NULL, scon,
> > NULL, true);
> >   
> >       return 0;
> >   }
> >   
> >   static void console_reset(DeviceState *dev)
> >   {
> > -   SCLPEvent *event = SCLP_EVENT(dev);
> > -   SCLPConsole *scon = SCLP_CONSOLE(event);
> > -
> > -   event->event_pending = false;
> > -   scon->iov_sclp = 0;
> > -   scon->iov_bs = 0;
> > -   scon->iov_data_len = 0;
> > -   scon->iov_sclp_rest = 0;
> > -   scon->notify = false;
> > +    SCLPEvent *event = SCLP_EVENT(dev);
> > +    SCLPConsole *scon = SCLP_CONSOLE(event);
> > +
> > +    scon->iov_sclp = 0;
> > +    scon->iov_bs = 0;
> > +    scon->iov_data_len = 0;
> > +    scon->iov_sclp_rest = 0;
> > +    scon->notify = false;
> > +
> > +    /* the guest defaults its terminal size on reset, announce the
> > real one */
> > +    scon->resize = true;
> > +    scon->resize_init = true;
> > +    event->event_pending = true;
> >   }
> 
> This is a style fix, included in a functional patch. I suppose it is 
> probably borderline, but it might be best to put this in its own
> patch.

I thought about that, but concluded that a 6-line indentation commit
would be too small to warrant its own patch. If you'd prefer it to be
split I could also send it as a seperate patch.

> 
> Other than that:
> Reviewed-by: Jason J. Herne <[email protected]>

Thanks

Reply via email to