From 3592fe0c919cf27a81d8e9f9b4f269553418bb01 Mon Sep 17 00:00:00 2001 From: Prasad J Pandit Date: Wed, 12 Oct 2016 11:28:08 +0530 Subject: char: serial: check divider value against baud base 16550A UART device uses an oscillator to generate frequencies (baud base), which decide communication speed. This speed could be changed by dividing it by a divider. If the divider is greater than the baud base, speed is set to zero, leading to a divide by zero error. Add check to avoid it. Reported-by: Huawei PSIRT Signed-off-by: Prasad J Pandit Message-Id: <1476251888-20238-1-git-send-email-ppandit@redhat.com> Signed-off-by: Paolo Bonzini --- hw/char/serial.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'hw/char/serial.c') diff --git a/hw/char/serial.c b/hw/char/serial.c index 3442f47..eec72b7 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -153,8 +153,9 @@ static void serial_update_parameters(SerialState *s) int speed, parity, data_bits, stop_bits, frame_size; QEMUSerialSetParams ssp; - if (s->divider == 0) + if (s->divider == 0 || s->divider > s->baudbase) { return; + } /* Start bit. */ frame_size = 1; -- cgit v1.1 From becdfa00cfa2995e859ccefa4b7d72a72eb96581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sat, 22 Oct 2016 12:52:51 +0300 Subject: char: replace PROP_CHR with CharBackend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Store the property in a CharBackend instead of CharDriverState*. This also replace systematically chr by chr.chr to access the CharDriverState*. The following patches will replace it with calls to qemu_chr_fe CharBackend functions. Signed-off-by: Marc-André Lureau Message-Id: <20161022095318.17775-12-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- hw/char/serial.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'hw/char/serial.c') diff --git a/hw/char/serial.c b/hw/char/serial.c index eec72b7..18c7482 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -182,7 +182,7 @@ static void serial_update_parameters(SerialState *s) ssp.data_bits = data_bits; ssp.stop_bits = stop_bits; s->char_transmit_time = (NANOSECONDS_PER_SECOND / speed) * frame_size; - qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); + qemu_chr_fe_ioctl(s->chr.chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); DPRINTF("speed=%d parity=%c data=%d stop=%d\n", speed, parity, data_bits, stop_bits); @@ -195,7 +195,8 @@ static void serial_update_msl(SerialState *s) timer_del(s->modem_status_poll); - if (qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP) { + if (qemu_chr_fe_ioctl(s->chr.chr, CHR_IOCTL_SERIAL_GET_TIOCM, + &flags) == -ENOTSUP) { s->poll_msl = -1; return; } @@ -260,11 +261,12 @@ static void serial_xmit(SerialState *s) if (s->mcr & UART_MCR_LOOP) { /* in loopback mode, say that we just received a char */ serial_receive1(s, &s->tsr, 1); - } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1 && + } else if (qemu_chr_fe_write(s->chr.chr, &s->tsr, 1) != 1 && s->tsr_retry < MAX_XMIT_RETRY) { assert(s->watch_tag == 0); - s->watch_tag = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP, - serial_watch_cb, s); + s->watch_tag = + qemu_chr_fe_add_watch(s->chr.chr, G_IO_OUT | G_IO_HUP, + serial_watch_cb, s); if (s->watch_tag > 0) { s->tsr_retry++; return; @@ -417,7 +419,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, break_enable = (val >> 6) & 1; if (break_enable != s->last_break_enable) { s->last_break_enable = break_enable; - qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK, + qemu_chr_fe_ioctl(s->chr.chr, CHR_IOCTL_SERIAL_SET_BREAK, &break_enable); } } @@ -432,7 +434,8 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, if (s->poll_msl >= 0 && old_mcr != s->mcr) { - qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags); + qemu_chr_fe_ioctl(s->chr.chr, + CHR_IOCTL_SERIAL_GET_TIOCM, &flags); flags &= ~(CHR_TIOCM_RTS | CHR_TIOCM_DTR); @@ -441,7 +444,8 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, if (val & UART_MCR_DTR) flags |= CHR_TIOCM_DTR; - qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_SET_TIOCM, &flags); + qemu_chr_fe_ioctl(s->chr.chr, + CHR_IOCTL_SERIAL_SET_TIOCM, &flags); /* Update the modem status after a one-character-send wait-time, since there may be a response from the device/computer at the other end of the serial line */ timer_mod(s->modem_status_poll, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time); @@ -486,7 +490,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size) serial_update_irq(s); if (!(s->mcr & UART_MCR_LOOP)) { /* in loopback mode, don't receive any data */ - qemu_chr_accept_input(s->chr); + qemu_chr_accept_input(s->chr.chr); } } break; @@ -659,7 +663,7 @@ static int serial_post_load(void *opaque, int version_id) } assert(s->watch_tag == 0); - s->watch_tag = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP, + s->watch_tag = qemu_chr_fe_add_watch(s->chr.chr, G_IO_OUT | G_IO_HUP, serial_watch_cb, s); } else { /* tsr_retry == 0 implies LSR.TEMT = 1 (transmitter empty). */ @@ -884,7 +888,7 @@ static void serial_reset(void *opaque) void serial_realize_core(SerialState *s, Error **errp) { - if (!s->chr) { + if (!s->chr.chr) { error_setg(errp, "Can't create serial device, empty char device"); return; } @@ -894,7 +898,7 @@ void serial_realize_core(SerialState *s, Error **errp) s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) fifo_timeout_int, s); qemu_register_reset(serial_reset, s); - qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1, + qemu_chr_add_handlers(s->chr.chr, serial_can_receive1, serial_receive1, serial_event, s); fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH); fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH); @@ -903,7 +907,7 @@ void serial_realize_core(SerialState *s, Error **errp) void serial_exit_core(SerialState *s) { - qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL); + qemu_chr_add_handlers(s->chr.chr, NULL, NULL, NULL, NULL); qemu_unregister_reset(serial_reset, s); } @@ -933,7 +937,7 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase, s->irq = irq; s->baudbase = baudbase; - s->chr = chr; + qemu_chr_fe_init(&s->chr, chr, &error_abort); serial_realize_core(s, &error_fatal); vmstate_register(NULL, base, &vmstate_serial, s); @@ -990,7 +994,7 @@ SerialState *serial_mm_init(MemoryRegion *address_space, s->it_shift = it_shift; s->irq = irq; s->baudbase = baudbase; - s->chr = chr; + qemu_chr_fe_init(&s->chr, chr, &error_abort); serial_realize_core(s, &error_fatal); vmstate_register(NULL, base, &vmstate_serial, s); -- cgit v1.1 From 7fa47e2a80e1c204533340f65909b7fc7c6b276f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sat, 22 Oct 2016 12:52:53 +0300 Subject: char: rename some frontend functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qemu_chr_accept_input() and qemu_chr_disconnect() are only used by frontend, so use qemu_chr_fe prefix. Signed-off-by: Marc-André Lureau Message-Id: <20161022095318.17775-14-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- hw/char/serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw/char/serial.c') diff --git a/hw/char/serial.c b/hw/char/serial.c index 18c7482..4489bf1 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -490,7 +490,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size) serial_update_irq(s); if (!(s->mcr & UART_MCR_LOOP)) { /* in loopback mode, don't receive any data */ - qemu_chr_accept_input(s->chr.chr); + qemu_chr_fe_accept_input(s->chr.chr); } } break; -- cgit v1.1 From 5345fdb4467816c44f6752b3a1f4e73aa25919f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sat, 22 Oct 2016 12:52:55 +0300 Subject: char: use qemu_chr_fe* functions with CharBackend argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also switches from qemu_chr_add_handlers() to qemu_chr_fe_set_handlers(). Note that qemu_chr_fe_set_handlers() now takes the focus when fe_open (qemu_chr_add_handlers() did take the focus) Signed-off-by: Marc-André Lureau Message-Id: <20161022095318.17775-16-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- hw/char/serial.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'hw/char/serial.c') diff --git a/hw/char/serial.c b/hw/char/serial.c index 4489bf1..509bc25 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -182,7 +182,7 @@ static void serial_update_parameters(SerialState *s) ssp.data_bits = data_bits; ssp.stop_bits = stop_bits; s->char_transmit_time = (NANOSECONDS_PER_SECOND / speed) * frame_size; - qemu_chr_fe_ioctl(s->chr.chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); + qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); DPRINTF("speed=%d parity=%c data=%d stop=%d\n", speed, parity, data_bits, stop_bits); @@ -195,7 +195,7 @@ static void serial_update_msl(SerialState *s) timer_del(s->modem_status_poll); - if (qemu_chr_fe_ioctl(s->chr.chr, CHR_IOCTL_SERIAL_GET_TIOCM, + if (qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP) { s->poll_msl = -1; return; @@ -261,11 +261,11 @@ static void serial_xmit(SerialState *s) if (s->mcr & UART_MCR_LOOP) { /* in loopback mode, say that we just received a char */ serial_receive1(s, &s->tsr, 1); - } else if (qemu_chr_fe_write(s->chr.chr, &s->tsr, 1) != 1 && + } else if (qemu_chr_fe_write(&s->chr, &s->tsr, 1) != 1 && s->tsr_retry < MAX_XMIT_RETRY) { assert(s->watch_tag == 0); s->watch_tag = - qemu_chr_fe_add_watch(s->chr.chr, G_IO_OUT | G_IO_HUP, + qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP, serial_watch_cb, s); if (s->watch_tag > 0) { s->tsr_retry++; @@ -419,8 +419,8 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, break_enable = (val >> 6) & 1; if (break_enable != s->last_break_enable) { s->last_break_enable = break_enable; - qemu_chr_fe_ioctl(s->chr.chr, CHR_IOCTL_SERIAL_SET_BREAK, - &break_enable); + qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK, + &break_enable); } } break; @@ -434,8 +434,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, if (s->poll_msl >= 0 && old_mcr != s->mcr) { - qemu_chr_fe_ioctl(s->chr.chr, - CHR_IOCTL_SERIAL_GET_TIOCM, &flags); + qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_GET_TIOCM, &flags); flags &= ~(CHR_TIOCM_RTS | CHR_TIOCM_DTR); @@ -444,8 +443,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, if (val & UART_MCR_DTR) flags |= CHR_TIOCM_DTR; - qemu_chr_fe_ioctl(s->chr.chr, - CHR_IOCTL_SERIAL_SET_TIOCM, &flags); + qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_TIOCM, &flags); /* Update the modem status after a one-character-send wait-time, since there may be a response from the device/computer at the other end of the serial line */ timer_mod(s->modem_status_poll, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time); @@ -490,7 +488,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size) serial_update_irq(s); if (!(s->mcr & UART_MCR_LOOP)) { /* in loopback mode, don't receive any data */ - qemu_chr_fe_accept_input(s->chr.chr); + qemu_chr_fe_accept_input(&s->chr); } } break; @@ -663,7 +661,7 @@ static int serial_post_load(void *opaque, int version_id) } assert(s->watch_tag == 0); - s->watch_tag = qemu_chr_fe_add_watch(s->chr.chr, G_IO_OUT | G_IO_HUP, + s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP, serial_watch_cb, s); } else { /* tsr_retry == 0 implies LSR.TEMT = 1 (transmitter empty). */ @@ -888,7 +886,7 @@ static void serial_reset(void *opaque) void serial_realize_core(SerialState *s, Error **errp) { - if (!s->chr.chr) { + if (!qemu_chr_fe_get_driver(&s->chr)) { error_setg(errp, "Can't create serial device, empty char device"); return; } @@ -898,8 +896,8 @@ void serial_realize_core(SerialState *s, Error **errp) s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) fifo_timeout_int, s); qemu_register_reset(serial_reset, s); - qemu_chr_add_handlers(s->chr.chr, serial_can_receive1, serial_receive1, - serial_event, s); + qemu_chr_fe_set_handlers(&s->chr, serial_can_receive1, serial_receive1, + serial_event, s, NULL); fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH); fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH); serial_reset(s); @@ -907,7 +905,7 @@ void serial_realize_core(SerialState *s, Error **errp) void serial_exit_core(SerialState *s) { - qemu_chr_add_handlers(s->chr.chr, NULL, NULL, NULL, NULL); + qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, NULL, NULL); qemu_unregister_reset(serial_reset, s); } -- cgit v1.1 From c39860e6dc90f6ee2e82ee078f978c5d7f3df86a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sat, 22 Oct 2016 12:52:58 +0300 Subject: char: replace qemu_chr_claim/release with qemu_chr_fe_init/deinit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that all front end use qemu_chr_fe_init(), we can move chardev claiming in init(), and add a function deinit() to release the chardev and cleanup handlers. The qemu_chr_fe_claim_no_fail() for property are gone, since the property will raise an error instead. In other cases, where there is already an error path, an error is raised instead. Finally, other cases are handled by &error_abort in qemu_chr_fe_init(). Signed-off-by: Marc-André Lureau Message-Id: <20161022095318.17775-19-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- hw/char/serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw/char/serial.c') diff --git a/hw/char/serial.c b/hw/char/serial.c index 509bc25..54f80c6 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -905,7 +905,7 @@ void serial_realize_core(SerialState *s, Error **errp) void serial_exit_core(SerialState *s) { - qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, NULL, NULL); + qemu_chr_fe_deinit(&s->chr); qemu_unregister_reset(serial_reset, s); } -- cgit v1.1 From 39ab61c6d0757ed95badc9315857effdb64e4aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sat, 22 Oct 2016 12:53:03 +0300 Subject: char: remove explicit_fe_open, use a set_handlers argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to keep explicit_fe_open around if it affects only a qemu_chr_fe_set_handlers(). Use an additional argument instead. Signed-off-by: Marc-André Lureau Message-Id: <20161022095318.17775-24-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- hw/char/serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw/char/serial.c') diff --git a/hw/char/serial.c b/hw/char/serial.c index 54f80c6..ffbacd8 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -897,7 +897,7 @@ void serial_realize_core(SerialState *s, Error **errp) qemu_register_reset(serial_reset, s); qemu_chr_fe_set_handlers(&s->chr, serial_can_receive1, serial_receive1, - serial_event, s, NULL); + serial_event, s, NULL, true); fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH); fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH); serial_reset(s); -- cgit v1.1