mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
hw: replace most use of qemu_chr_fe_write with qemu_chr_fe_write_all
The qemu_chr_fe_write method will return -1 on EAGAIN if the chardev backend write would block. Almost no callers of the qemu_chr_fe_write() method check the return value, instead blindly assuming data was successfully sent. In most cases this will lead to silent data loss on interactive consoles, but in some cases (eg RNG EGD) it'll just cause corruption of the protocol being spoken. We unfortunately can't fix the virtio-console code, due to a bug in the Linux guest drivers, which would cause the entire Linux kernel to hang if we delay processing of the incoming data in any way. Fixing this requires first fixing the guest driver to not hold spinlocks while writing to the hvc device backend. Fixes bug: https://bugs.launchpad.net/qemu/+bug/1586756 Signed-off-by: Daniel P. Berrange <berrange@redhat.com> Message-Id: <1473170165-540-4-git-send-email-berrange@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
committed by
Paolo Bonzini
parent
7983e82933
commit
6ab3fc32ea
+3
-1
@@ -41,7 +41,9 @@ static void rng_egd_request_entropy(RngBackend *b, RngRequest *req)
|
||||
header[0] = 0x02;
|
||||
header[1] = len;
|
||||
|
||||
qemu_chr_fe_write(s->chr, header, sizeof(header));
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(s->chr, header, sizeof(header));
|
||||
|
||||
size -= len;
|
||||
}
|
||||
|
||||
@@ -402,7 +402,9 @@ static void put_buffer(GDBState *s, const uint8_t *buf, int len)
|
||||
}
|
||||
}
|
||||
#else
|
||||
qemu_chr_fe_write(s->chr, buf, len);
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(s->chr, buf, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -769,14 +769,16 @@ static void omap_sti_fifo_write(void *opaque, hwaddr addr,
|
||||
|
||||
if (ch == STI_TRACE_CONTROL_CHANNEL) {
|
||||
/* Flush channel <i>value</i>. */
|
||||
qemu_chr_fe_write(s->chr, (const uint8_t *) "\r", 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, (const uint8_t *) "\r", 1);
|
||||
} else if (ch == STI_TRACE_CONSOLE_CHANNEL || 1) {
|
||||
if (value == 0xc0 || value == 0xc3) {
|
||||
/* Open channel <i>ch</i>. */
|
||||
} else if (value == 0x00)
|
||||
qemu_chr_fe_write(s->chr, (const uint8_t *) "\n", 1);
|
||||
qemu_chr_fe_write_all(s->chr, (const uint8_t *) "\n", 1);
|
||||
else
|
||||
qemu_chr_fe_write(s->chr, &byte, 1);
|
||||
qemu_chr_fe_write_all(s->chr, &byte, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1903,7 +1903,9 @@ static void pxa2xx_fir_write(void *opaque, hwaddr addr,
|
||||
else
|
||||
ch = ~value;
|
||||
if (s->chr && s->enable && (s->control[0] & (1 << 3))) /* TXE */
|
||||
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;
|
||||
case ICSR0:
|
||||
s->status[0] &= ~(value & 0x66);
|
||||
|
||||
+3
-1
@@ -1108,7 +1108,9 @@ static void strongarm_uart_tx(void *opaque)
|
||||
if (s->utcr3 & UTCR3_LBM) /* loopback */ {
|
||||
strongarm_uart_receive(s, &s->tx_fifo[s->tx_start], 1);
|
||||
} else if (s->chr) {
|
||||
qemu_chr_fe_write(s->chr, &s->tx_fifo[s->tx_start], 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_fifo[s->tx_start], 1);
|
||||
}
|
||||
|
||||
s->tx_start = (s->tx_start + 1) % 8;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+3
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+3
-1
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
+3
-1
@@ -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) {
|
||||
|
||||
+3
-1
@@ -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;
|
||||
|
||||
+3
-1
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user