diff options
Diffstat (limited to 'hw/char')
-rw-r--r-- | hw/char/bcm2835_aux.c | 4 | ||||
-rw-r--r-- | hw/char/debugcon.c | 4 | ||||
-rw-r--r-- | hw/char/digic-uart.c | 2 | ||||
-rw-r--r-- | hw/char/escc.c | 4 | ||||
-rw-r--r-- | hw/char/etraxfs_ser.c | 4 | ||||
-rw-r--r-- | hw/char/exynos4210_uart.c | 4 | ||||
-rw-r--r-- | hw/char/grlib_apbuart.c | 4 | ||||
-rw-r--r-- | hw/char/imx_serial.c | 4 | ||||
-rw-r--r-- | hw/char/ipoctal232.c | 4 | ||||
-rw-r--r-- | hw/char/lm32_juart.c | 2 | ||||
-rw-r--r-- | hw/char/lm32_uart.c | 2 | ||||
-rw-r--r-- | hw/char/mcf_uart.c | 4 | ||||
-rw-r--r-- | hw/char/parallel.c | 4 | ||||
-rw-r--r-- | hw/char/pl011.c | 4 | ||||
-rw-r--r-- | hw/char/sclpconsole-lm.c | 4 | ||||
-rw-r--r-- | hw/char/sclpconsole.c | 2 | ||||
-rw-r--r-- | hw/char/sh_serial.c | 4 | ||||
-rw-r--r-- | hw/char/spapr_vty.c | 5 | ||||
-rw-r--r-- | hw/char/stm32f2xx_usart.c | 2 | ||||
-rw-r--r-- | hw/char/virtio-console.c | 21 | ||||
-rw-r--r-- | hw/char/xilinx_uartlite.c | 4 |
21 files changed, 76 insertions, 16 deletions
diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c index 319f1652f6..f7a845d3e2 100644 --- a/hw/char/bcm2835_aux.c +++ b/hw/char/bcm2835_aux.c @@ -169,7 +169,9 @@ static void bcm2835_aux_write(void *opaque, hwaddr offset, uint64_t value, /* "DLAB bit set means access baudrate register" is NYI */ ch = value; if (s->chr) { - qemu_chr_fe_write(s->chr, &ch, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(s->chr, &ch, 1); } break; diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c index e7f025ec67..4402033861 100644 --- a/hw/char/debugcon.c +++ b/hw/char/debugcon.c @@ -60,7 +60,9 @@ static void debugcon_ioport_write(void *opaque, hwaddr addr, uint64_t val, printf(" [debugcon: write addr=0x%04" HWADDR_PRIx " val=0x%02" PRIx64 "]\n", addr, val); #endif - qemu_chr_fe_write(s->chr, &ch, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(s->chr, &ch, 1); } diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c index c7604e6766..e96a9b2d8d 100644 --- a/hw/char/digic-uart.c +++ b/hw/char/digic-uart.c @@ -77,6 +77,8 @@ static void digic_uart_write(void *opaque, hwaddr addr, uint64_t value, switch (addr) { case R_TX: if (s->chr) { + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ qemu_chr_fe_write_all(s->chr, &ch, 1); } break; diff --git a/hw/char/escc.c b/hw/char/escc.c index 31a5f902f9..aa1739762b 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -557,7 +557,9 @@ static void escc_mem_write(void *opaque, hwaddr addr, s->tx = val; if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled if (s->chr) - qemu_chr_fe_write(s->chr, &s->tx, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(s->chr, &s->tx, 1); else if (s->type == kbd && !s->disabled) { handle_kbd_command(s, val); } diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c index 04ca04fe2c..c99cc5d130 100644 --- a/hw/char/etraxfs_ser.c +++ b/hw/char/etraxfs_ser.c @@ -126,7 +126,9 @@ ser_write(void *opaque, hwaddr addr, switch (addr) { case RW_DOUT: - qemu_chr_fe_write(s->chr, &ch, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(s->chr, &ch, 1); s->regs[R_INTR] |= 3; s->pending_tx = 1; s->regs[addr] = value; diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c index 885ecc027b..1107578138 100644 --- a/hw/char/exynos4210_uart.c +++ b/hw/char/exynos4210_uart.c @@ -387,7 +387,9 @@ static void exynos4210_uart_write(void *opaque, hwaddr offset, s->reg[I_(UTRSTAT)] &= ~(UTRSTAT_TRANSMITTER_EMPTY | UTRSTAT_Tx_BUFFER_EMPTY); ch = (uint8_t)val; - qemu_chr_fe_write(s->chr, &ch, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(s->chr, &ch, 1); #if DEBUG_Tx_DATA fprintf(stderr, "%c", ch); #endif diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c index 871524c82f..778148a15e 100644 --- a/hw/char/grlib_apbuart.c +++ b/hw/char/grlib_apbuart.c @@ -203,7 +203,9 @@ static void grlib_apbuart_write(void *opaque, hwaddr addr, /* Transmit when character device available and transmitter enabled */ if ((uart->chr) && (uart->control & UART_TRANSMIT_ENABLE)) { c = value & 0xFF; - qemu_chr_fe_write(uart->chr, &c, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(uart->chr, &c, 1); /* Generate interrupt */ if (uart->control & UART_TRANSMIT_INTERRUPT) { qemu_irq_pulse(uart->irq); diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c index 44856d671e..5c3fa61e4c 100644 --- a/hw/char/imx_serial.c +++ b/hw/char/imx_serial.c @@ -182,7 +182,9 @@ static void imx_serial_write(void *opaque, hwaddr offset, ch = value; if (s->ucr2 & UCR2_TXEN) { if (s->chr) { - qemu_chr_fe_write(s->chr, &ch, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(s->chr, &ch, 1); } s->usr1 &= ~USR1_TRDY; imx_update(s); diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c index 9ead32af60..2859fdd7fb 100644 --- a/hw/char/ipoctal232.c +++ b/hw/char/ipoctal232.c @@ -360,7 +360,9 @@ static void io_write(IPackDevice *ip, uint8_t addr, uint16_t val) DPRINTF("Write THR%c (0x%x)\n", channel + 'a', reg); if (ch->dev) { uint8_t thr = reg; - qemu_chr_fe_write(ch->dev, &thr, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(ch->dev, &thr, 1); } } else { DPRINTF("Write THR%c (0x%x), Tx disabled\n", channel + 'a', reg); diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c index 28c2cf702d..cb1ac76731 100644 --- a/hw/char/lm32_juart.c +++ b/hw/char/lm32_juart.c @@ -76,6 +76,8 @@ void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx) s->jtx = jtx; if (s->chr) { + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ qemu_chr_fe_write_all(s->chr, &ch, 1); } } diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c index b5c760dda3..be93697a39 100644 --- a/hw/char/lm32_uart.c +++ b/hw/char/lm32_uart.c @@ -178,6 +178,8 @@ static void uart_write(void *opaque, hwaddr addr, switch (addr) { case R_RXTX: if (s->chr) { + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ qemu_chr_fe_write_all(s->chr, &ch, 1); } break; diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c index 3c0438fd79..c184859c83 100644 --- a/hw/char/mcf_uart.c +++ b/hw/char/mcf_uart.c @@ -114,7 +114,9 @@ static void mcf_uart_do_tx(mcf_uart_state *s) { if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) { if (s->chr) - qemu_chr_fe_write(s->chr, (unsigned char *)&s->tb, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(s->chr, (unsigned char *)&s->tb, 1); s->sr |= MCF_UART_TxEMP; } if (s->tx_enabled) { diff --git a/hw/char/parallel.c b/hw/char/parallel.c index fa085667ff..da22e36356 100644 --- a/hw/char/parallel.c +++ b/hw/char/parallel.c @@ -129,7 +129,9 @@ parallel_ioport_write_sw(void *opaque, uint32_t addr, uint32_t val) if (val & PARA_CTR_STROBE) { s->status &= ~PARA_STS_BUSY; if ((s->control & PARA_CTR_STROBE) == 0) - qemu_chr_fe_write(s->chr, &s->dataw, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(s->chr, &s->dataw, 1); } else { if (s->control & PARA_CTR_INTEN) { s->irq_pending = 1; diff --git a/hw/char/pl011.c b/hw/char/pl011.c index c0fbf8a874..786e605fdd 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -146,7 +146,9 @@ static void pl011_write(void *opaque, hwaddr offset, /* ??? Check if transmitter is enabled. */ ch = value; if (s->chr) - qemu_chr_fe_write(s->chr, &ch, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(s->chr, &ch, 1); s->int_level |= PL011_INT_TX; pl011_update(s); break; diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c index dbe753147b..9a563269e6 100644 --- a/hw/char/sclpconsole-lm.c +++ b/hw/char/sclpconsole-lm.c @@ -89,7 +89,9 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) scon->buf[scon->length] = *buf; scon->length += 1; if (scon->echo) { - qemu_chr_fe_write(scon->chr, buf, size); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(scon->chr, buf, size); } } diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index d22464826b..a75ad4f60a 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -168,6 +168,8 @@ static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf, return len; } + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ return qemu_chr_fe_write_all(scon->chr, buf, len); } diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c index 4c55dcb7dc..97ce5629a4 100644 --- a/hw/char/sh_serial.c +++ b/hw/char/sh_serial.c @@ -111,7 +111,9 @@ static void sh_serial_write(void *opaque, hwaddr offs, case 0x0c: /* FTDR / TDR */ if (s->chr) { ch = val; - qemu_chr_fe_write(s->chr, &ch, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(s->chr, &ch, 1); } s->dr = val; s->flags &= ~SH_SERIAL_FLAG_TDE; diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c index 3498d7b052..9aeafc0c42 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -60,8 +60,9 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len) { VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev); - /* FIXME: should check the qemu_chr_fe_write() return value */ - qemu_chr_fe_write(dev->chardev, buf, len); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(dev->chardev, buf, len); } static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp) diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c index 15657abda9..4c6640dbe9 100644 --- a/hw/char/stm32f2xx_usart.c +++ b/hw/char/stm32f2xx_usart.c @@ -153,6 +153,8 @@ static void stm32f2xx_usart_write(void *opaque, hwaddr addr, if (value < 0xF000) { ch = value; if (s->chr) { + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ qemu_chr_fe_write_all(s->chr, &ch, 1); } s->usart_sr |= USART_SR_TC; diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c index 4f0e03d3b7..d44c18c128 100644 --- a/hw/char/virtio-console.c +++ b/hw/char/virtio-console.c @@ -68,6 +68,27 @@ static ssize_t flush_buf(VirtIOSerialPort *port, */ if (ret < 0) ret = 0; + + /* XXX we should be queuing data to send later for the + * console devices too rather than silently dropping + * console data on EAGAIN. The Linux virtio-console + * hvc driver though does sends with spinlocks held, + * so if we enable throttling that'll stall the entire + * guest kernel, not merely the process writing to the + * console. + * + * While we could queue data for later write without + * enabling throttling, this would result in the guest + * being able to trigger arbitrary memory usage in QEMU + * buffering data for later writes. + * + * So fixing this problem likely requires fixing the + * Linux virtio-console hvc driver to not hold spinlocks + * while writing, and instead merely block the process + * that's writing. QEMU would then need some way to detect + * if the guest had the fixed driver too, before we can + * use throttling on host side. + */ if (!k->is_console) { virtio_serial_throttle_port(port, true); if (!vcon->watch) { diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c index 4847efb29f..3766dc2c5b 100644 --- a/hw/char/xilinx_uartlite.c +++ b/hw/char/xilinx_uartlite.c @@ -144,7 +144,9 @@ uart_write(void *opaque, hwaddr addr, case R_TX: if (s->chr) - qemu_chr_fe_write(s->chr, &ch, 1); + /* XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks */ + qemu_chr_fe_write_all(s->chr, &ch, 1); s->regs[addr] = value; |