* [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop
@ 2023-07-10 17:50 Philippe Mathieu-Daudé
2023-07-10 17:50 ` [PATCH v2 01/11] hw/char/pl011: Restrict MemoryRegionOps implementation access sizes Philippe Mathieu-Daudé
` (10 more replies)
0 siblings, 11 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 17:50 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Philippe Mathieu-Daudé
Hi,
This series add support for (async) FIFO on the transmit path
of the PL011 UART.
Since v1:
- Restrict pl011_ops[] impl access_size,
- Do not check transmitter is enabled (Peter),
- Addressed Alex's review comments,
- Simplified migration trying to care about backward compat,
but still unsure...
Philippe Mathieu-Daudé (11):
hw/char/pl011: Restrict MemoryRegionOps implementation access sizes
hw/char/pl011: Display register name in trace events
hw/char/pl011: Remove duplicated PL011_INT_[RT]X definitions
hw/char/pl011: Replace magic values by register field definitions
hw/char/pl011: Split RX/TX path of pl011_reset_fifo()
hw/char/pl011: Extract pl011_write_txdata() from pl011_write()
hw/char/pl011: Extract pl011_read_rxdata() from pl011_read()
hw/char/pl011: Warn when using disabled transmitter
hw/char/pl011: Check if receiver is enabled
hw/char/pl011: Rename RX FIFO methods
hw/char/pl011: Implement TX FIFO
include/hw/char/pl011.h | 2 +
hw/char/pl011.c | 255 ++++++++++++++++++++++++++++++++--------
hw/char/trace-events | 12 +-
3 files changed, 215 insertions(+), 54 deletions(-)
--
2.38.1
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v2 01/11] hw/char/pl011: Restrict MemoryRegionOps implementation access sizes
2023-07-10 17:50 [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop Philippe Mathieu-Daudé
@ 2023-07-10 17:50 ` Philippe Mathieu-Daudé
2023-07-14 6:47 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 02/11] hw/char/pl011: Display register name in trace events Philippe Mathieu-Daudé
` (9 subsequent siblings)
10 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 17:50 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Philippe Mathieu-Daudé
The pl011_read() and pl011_write() handlers shift the offset
argument by 2, so are implemented on a 32-bit boundary.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
hw/char/pl011.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 77bbc2a982..73f1a3aea2 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -358,6 +358,8 @@ static const MemoryRegionOps pl011_ops = {
.read = pl011_read,
.write = pl011_write,
.endianness = DEVICE_NATIVE_ENDIAN,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
};
static bool pl011_clock_needed(void *opaque)
--
2.38.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 02/11] hw/char/pl011: Display register name in trace events
2023-07-10 17:50 [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop Philippe Mathieu-Daudé
2023-07-10 17:50 ` [PATCH v2 01/11] hw/char/pl011: Restrict MemoryRegionOps implementation access sizes Philippe Mathieu-Daudé
@ 2023-07-10 17:50 ` Philippe Mathieu-Daudé
2023-07-14 6:49 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 03/11] hw/char/pl011: Remove duplicated PL011_INT_[RT]X definitions Philippe Mathieu-Daudé
` (8 subsequent siblings)
10 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 17:50 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Philippe Mathieu-Daudé
To avoid knowing the register addresses by heart,
display their name along in the trace events.
Since the MMIO region is 4K wide (0x1000 bytes),
displaying the address with 3 digits is enough,
so reduce the address format.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
hw/char/pl011.c | 25 ++++++++++++++++++++++---
hw/char/trace-events | 4 ++--
2 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 73f1a3aea2..c3203e5b41 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -51,6 +51,7 @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr)
#define PL011_INT_TX 0x20
#define PL011_INT_RX 0x10
+/* Flag Register, UARTFR */
#define PL011_FLAG_TXFE 0x80
#define PL011_FLAG_RXFF 0x40
#define PL011_FLAG_TXFF 0x20
@@ -76,6 +77,24 @@ static const unsigned char pl011_id_arm[8] =
static const unsigned char pl011_id_luminary[8] =
{ 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
+static const char *pl011_regname(hwaddr offset)
+{
+ static const char *const rname[] = {
+ [0] = "DR", [1] = "RSR", [6] = "FR", [8] = "ILPR", [9] = "IBRD",
+ [10] = "FBRD", [11] = "LCRH", [12] = "CR", [13] = "IFLS", [14] = "IMSC",
+ [15] = "RIS", [16] = "MIS", [17] = "ICR", [18] = "DMACR",
+ };
+ unsigned idx = offset >> 2;
+
+ if (idx < ARRAY_SIZE(rname) && rname[idx]) {
+ return rname[idx];
+ }
+ if (idx >= 0x3f8 && idx <= 0x400) {
+ return "ID";
+ }
+ return "UNKN";
+}
+
/* Which bits in the interrupt status matter for each outbound IRQ line ? */
static const uint32_t irqmask[] = {
INT_E | INT_MS | INT_RT | INT_TX | INT_RX, /* combined IRQ */
@@ -191,7 +210,7 @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
break;
}
- trace_pl011_read(offset, r);
+ trace_pl011_read(offset, r, pl011_regname(offset));
return r;
}
@@ -234,7 +253,7 @@ static void pl011_write(void *opaque, hwaddr offset,
PL011State *s = (PL011State *)opaque;
unsigned char ch;
- trace_pl011_write(offset, value);
+ trace_pl011_write(offset, value, pl011_regname(offset));
switch (offset >> 2) {
case 0: /* UARTDR */
@@ -252,7 +271,7 @@ static void pl011_write(void *opaque, hwaddr offset,
case 6: /* UARTFR */
/* Writes to Flag register are ignored. */
break;
- case 8: /* UARTUARTILPR */
+ case 8: /* UARTILPR */
s->ilpr = value;
break;
case 9: /* UARTIBRD */
diff --git a/hw/char/trace-events b/hw/char/trace-events
index 2ecb36232e..babf4d35ea 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -54,9 +54,9 @@ escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=0x%0
# pl011.c
pl011_irq_state(int level) "irq state %d"
-pl011_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
+pl011_read(uint32_t addr, uint32_t value, const char *regname) "addr 0x%03x value 0x%08x reg %s"
pl011_read_fifo(int read_count) "FIFO read, read_count now %d"
-pl011_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
+pl011_write(uint32_t addr, uint32_t value, const char *regname) "addr 0x%03x value 0x%08x reg %s"
pl011_can_receive(uint32_t lcr, int read_count, int r) "LCR 0x%08x read_count %d returning %d"
pl011_put_fifo(uint32_t c, int read_count) "new char 0x%x read_count now %d"
pl011_put_fifo_full(void) "FIFO now full, RXFF set"
--
2.38.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 03/11] hw/char/pl011: Remove duplicated PL011_INT_[RT]X definitions
2023-07-10 17:50 [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop Philippe Mathieu-Daudé
2023-07-10 17:50 ` [PATCH v2 01/11] hw/char/pl011: Restrict MemoryRegionOps implementation access sizes Philippe Mathieu-Daudé
2023-07-10 17:50 ` [PATCH v2 02/11] hw/char/pl011: Display register name in trace events Philippe Mathieu-Daudé
@ 2023-07-10 17:50 ` Philippe Mathieu-Daudé
2023-07-14 6:50 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 04/11] hw/char/pl011: Replace magic values by register field definitions Philippe Mathieu-Daudé
` (7 subsequent siblings)
10 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 17:50 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Philippe Mathieu-Daudé
PL011_INT_TX duplicates INT_TX, and PL011_INT_RX INT_RX.
Follow other register fields definitions from this file,
keep the shorter form.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
hw/char/pl011.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index c3203e5b41..96675f52cc 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -48,9 +48,6 @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr)
return dev;
}
-#define PL011_INT_TX 0x20
-#define PL011_INT_RX 0x10
-
/* Flag Register, UARTFR */
#define PL011_FLAG_TXFE 0x80
#define PL011_FLAG_RXFF 0x40
@@ -157,7 +154,7 @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
s->flags |= PL011_FLAG_RXFE;
}
if (s->read_count == s->read_trigger - 1)
- s->int_level &= ~ PL011_INT_RX;
+ s->int_level &= ~ INT_RX;
trace_pl011_read_fifo(s->read_count);
s->rsr = c >> 8;
pl011_update(s);
@@ -262,7 +259,7 @@ static void pl011_write(void *opaque, hwaddr offset,
/* 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;
+ s->int_level |= INT_TX;
pl011_update(s);
break;
case 1: /* UARTRSR/UARTECR */
@@ -350,7 +347,7 @@ static void pl011_put_fifo(void *opaque, uint32_t value)
s->flags |= PL011_FLAG_RXFF;
}
if (s->read_count == s->read_trigger) {
- s->int_level |= PL011_INT_RX;
+ s->int_level |= INT_RX;
pl011_update(s);
}
}
--
2.38.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 04/11] hw/char/pl011: Replace magic values by register field definitions
2023-07-10 17:50 [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop Philippe Mathieu-Daudé
` (2 preceding siblings ...)
2023-07-10 17:50 ` [PATCH v2 03/11] hw/char/pl011: Remove duplicated PL011_INT_[RT]X definitions Philippe Mathieu-Daudé
@ 2023-07-10 17:50 ` Philippe Mathieu-Daudé
2023-07-14 6:54 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 05/11] hw/char/pl011: Split RX/TX path of pl011_reset_fifo() Philippe Mathieu-Daudé
` (6 subsequent siblings)
10 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 17:50 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Philippe Mathieu-Daudé
0x400 is Data Register Break Error (DR_BE),
0x10 is Line Control Register Fifo Enabled (LCR_FEN)
and 0x1 is Send Break (LCR_BRK).
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
hw/char/pl011.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 96675f52cc..58edeb9ddb 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -54,6 +54,9 @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr)
#define PL011_FLAG_TXFF 0x20
#define PL011_FLAG_RXFE 0x10
+/* Data Register, UARTDR */
+#define DR_BE (1 << 10)
+
/* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */
#define INT_OE (1 << 10)
#define INT_BE (1 << 9)
@@ -69,6 +72,10 @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr)
#define INT_E (INT_OE | INT_BE | INT_PE | INT_FE)
#define INT_MS (INT_RI | INT_DSR | INT_DCD | INT_CTS)
+/* Line Control Register, UARTLCR_H */
+#define LCR_FEN (1 << 4)
+#define LCR_BRK (1 << 0)
+
static const unsigned char pl011_id_arm[8] =
{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
static const unsigned char pl011_id_luminary[8] =
@@ -116,7 +123,7 @@ static void pl011_update(PL011State *s)
static bool pl011_is_fifo_enabled(PL011State *s)
{
- return (s->lcr & 0x10) != 0;
+ return (s->lcr & LCR_FEN) != 0;
}
static inline unsigned pl011_get_fifo_depth(PL011State *s)
@@ -218,7 +225,7 @@ static void pl011_set_read_trigger(PL011State *s)
the threshold. However linux only reads the FIFO in response to an
interrupt. Triggering the interrupt when the FIFO is non-empty seems
to make things work. */
- if (s->lcr & 0x10)
+ if (s->lcr & LCR_FEN)
s->read_trigger = (s->ifl >> 1) & 0x1c;
else
#endif
@@ -281,11 +288,11 @@ static void pl011_write(void *opaque, hwaddr offset,
break;
case 11: /* UARTLCR_H */
/* Reset the FIFO state on FIFO enable or disable */
- if ((s->lcr ^ value) & 0x10) {
+ if ((s->lcr ^ value) & LCR_FEN) {
pl011_reset_fifo(s);
}
- if ((s->lcr ^ value) & 0x1) {
- int break_enable = value & 0x1;
+ if ((s->lcr ^ value) & LCR_BRK) {
+ int break_enable = value & LCR_BRK;
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
&break_enable);
}
@@ -359,8 +366,9 @@ static void pl011_receive(void *opaque, const uint8_t *buf, int size)
static void pl011_event(void *opaque, QEMUChrEvent event)
{
- if (event == CHR_EVENT_BREAK)
- pl011_put_fifo(opaque, 0x400);
+ if (event == CHR_EVENT_BREAK) {
+ pl011_put_fifo(opaque, DR_BE);
+ }
}
static void pl011_clock_update(void *opaque, ClockEvent event)
--
2.38.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 05/11] hw/char/pl011: Split RX/TX path of pl011_reset_fifo()
2023-07-10 17:50 [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop Philippe Mathieu-Daudé
` (3 preceding siblings ...)
2023-07-10 17:50 ` [PATCH v2 04/11] hw/char/pl011: Replace magic values by register field definitions Philippe Mathieu-Daudé
@ 2023-07-10 17:50 ` Philippe Mathieu-Daudé
2023-07-14 6:56 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 06/11] hw/char/pl011: Extract pl011_write_txdata() from pl011_write() Philippe Mathieu-Daudé
` (5 subsequent siblings)
10 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 17:50 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Philippe Mathieu-Daudé
To be able to reset the RX or TX FIFO separately,
split pl011_reset_fifo() in two.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
hw/char/pl011.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 58edeb9ddb..1f07c7b021 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -132,14 +132,21 @@ static inline unsigned pl011_get_fifo_depth(PL011State *s)
return pl011_is_fifo_enabled(s) ? PL011_FIFO_DEPTH : 1;
}
-static inline void pl011_reset_fifo(PL011State *s)
+static inline void pl011_reset_rx_fifo(PL011State *s)
{
s->read_count = 0;
s->read_pos = 0;
/* Reset FIFO flags */
- s->flags &= ~(PL011_FLAG_RXFF | PL011_FLAG_TXFF);
- s->flags |= PL011_FLAG_RXFE | PL011_FLAG_TXFE;
+ s->flags &= ~PL011_FLAG_RXFF;
+ s->flags |= PL011_FLAG_RXFE;
+}
+
+static inline void pl011_reset_tx_fifo(PL011State *s)
+{
+ /* Reset FIFO flags */
+ s->flags &= ~PL011_FLAG_TXFF;
+ s->flags |= PL011_FLAG_TXFE;
}
static uint64_t pl011_read(void *opaque, hwaddr offset,
@@ -289,7 +296,8 @@ static void pl011_write(void *opaque, hwaddr offset,
case 11: /* UARTLCR_H */
/* Reset the FIFO state on FIFO enable or disable */
if ((s->lcr ^ value) & LCR_FEN) {
- pl011_reset_fifo(s);
+ pl011_reset_rx_fifo(s);
+ pl011_reset_tx_fifo(s);
}
if ((s->lcr ^ value) & LCR_BRK) {
int break_enable = value & LCR_BRK;
@@ -506,7 +514,8 @@ static void pl011_reset(DeviceState *dev)
s->ifl = 0x12;
s->cr = 0x300;
s->flags = 0;
- pl011_reset_fifo(s);
+ pl011_reset_rx_fifo(s);
+ pl011_reset_tx_fifo(s);
}
static void pl011_class_init(ObjectClass *oc, void *data)
--
2.38.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 06/11] hw/char/pl011: Extract pl011_write_txdata() from pl011_write()
2023-07-10 17:50 [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop Philippe Mathieu-Daudé
` (4 preceding siblings ...)
2023-07-10 17:50 ` [PATCH v2 05/11] hw/char/pl011: Split RX/TX path of pl011_reset_fifo() Philippe Mathieu-Daudé
@ 2023-07-10 17:50 ` Philippe Mathieu-Daudé
2023-07-14 6:58 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 07/11] hw/char/pl011: Extract pl011_read_rxdata() from pl011_read() Philippe Mathieu-Daudé
` (4 subsequent siblings)
10 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 17:50 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Philippe Mathieu-Daudé
When implementing FIFO, this code will become more complex.
Start by factoring it out to a new pl011_write_txdata() function.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
hw/char/pl011.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 1f07c7b021..7bc7819d8b 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -149,6 +149,17 @@ static inline void pl011_reset_tx_fifo(PL011State *s)
s->flags |= PL011_FLAG_TXFE;
}
+static void pl011_write_txdata(PL011State *s, const uint8_t *buf, int length)
+{
+ /* ??? Check if transmitter is enabled. */
+
+ /* 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, 1);
+ s->int_level |= INT_TX;
+ pl011_update(s);
+}
+
static uint64_t pl011_read(void *opaque, hwaddr offset,
unsigned size)
{
@@ -262,19 +273,12 @@ static void pl011_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
PL011State *s = (PL011State *)opaque;
- unsigned char ch;
trace_pl011_write(offset, value, pl011_regname(offset));
switch (offset >> 2) {
case 0: /* UARTDR */
- /* ??? Check if transmitter is enabled. */
- ch = value;
- /* 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 |= INT_TX;
- pl011_update(s);
+ pl011_write_txdata(s, (uint8_t *) &value, 1);
break;
case 1: /* UARTRSR/UARTECR */
s->rsr = 0;
--
2.38.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 07/11] hw/char/pl011: Extract pl011_read_rxdata() from pl011_read()
2023-07-10 17:50 [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop Philippe Mathieu-Daudé
` (5 preceding siblings ...)
2023-07-10 17:50 ` [PATCH v2 06/11] hw/char/pl011: Extract pl011_write_txdata() from pl011_write() Philippe Mathieu-Daudé
@ 2023-07-10 17:50 ` Philippe Mathieu-Daudé
2023-07-14 7:00 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 08/11] hw/char/pl011: Warn when using disabled transmitter Philippe Mathieu-Daudé
` (3 subsequent siblings)
10 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 17:50 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Philippe Mathieu-Daudé
To keep MemoryRegionOps read/write handlers with similar logic,
factor pl011_read_txdata() out of pl011_read(), similar to the
previous commit did to pl011_write().
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
hw/char/pl011.c | 40 +++++++++++++++++++++++-----------------
1 file changed, 23 insertions(+), 17 deletions(-)
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 7bc7819d8b..e2e3d48b91 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -160,31 +160,37 @@ static void pl011_write_txdata(PL011State *s, const uint8_t *buf, int length)
pl011_update(s);
}
+static uint32_t pl011_read_rxdata(PL011State *s)
+{
+ uint32_t c;
+
+ s->flags &= ~PL011_FLAG_RXFF;
+ c = s->read_fifo[s->read_pos];
+ if (s->read_count > 0) {
+ s->read_count--;
+ s->read_pos = (s->read_pos + 1) & (pl011_get_fifo_depth(s) - 1);
+ }
+ if (s->read_count == 0) {
+ s->flags |= PL011_FLAG_RXFE;
+ }
+ if (s->read_count == s->read_trigger - 1)
+ s->int_level &= ~ INT_RX;
+ trace_pl011_read_fifo(s->read_count);
+ s->rsr = c >> 8;
+ pl011_update(s);
+ qemu_chr_fe_accept_input(&s->chr);
+ return c;
+}
+
static uint64_t pl011_read(void *opaque, hwaddr offset,
unsigned size)
{
PL011State *s = (PL011State *)opaque;
- uint32_t c;
uint64_t r;
switch (offset >> 2) {
case 0: /* UARTDR */
- s->flags &= ~PL011_FLAG_RXFF;
- c = s->read_fifo[s->read_pos];
- if (s->read_count > 0) {
- s->read_count--;
- s->read_pos = (s->read_pos + 1) & (pl011_get_fifo_depth(s) - 1);
- }
- if (s->read_count == 0) {
- s->flags |= PL011_FLAG_RXFE;
- }
- if (s->read_count == s->read_trigger - 1)
- s->int_level &= ~ INT_RX;
- trace_pl011_read_fifo(s->read_count);
- s->rsr = c >> 8;
- pl011_update(s);
- qemu_chr_fe_accept_input(&s->chr);
- r = c;
+ r = pl011_read_rxdata(s);
break;
case 1: /* UARTRSR */
r = s->rsr;
--
2.38.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 08/11] hw/char/pl011: Warn when using disabled transmitter
2023-07-10 17:50 [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop Philippe Mathieu-Daudé
` (6 preceding siblings ...)
2023-07-10 17:50 ` [PATCH v2 07/11] hw/char/pl011: Extract pl011_read_rxdata() from pl011_read() Philippe Mathieu-Daudé
@ 2023-07-10 17:50 ` Philippe Mathieu-Daudé
2023-07-14 7:01 ` Richard Henderson
2023-07-10 17:51 ` [PATCH v2 09/11] hw/char/pl011: Check if receiver is enabled Philippe Mathieu-Daudé
` (2 subsequent siblings)
10 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 17:50 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Philippe Mathieu-Daudé
We shouldn't transmit characters when the full UART or its
transmitter is disabled. However we don't want to break the
possibly incomplete "my first bare metal assembly program"s,
so we choose to simply display a warning when this occurs.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
hw/char/pl011.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index e2e3d48b91..03dce0a1ec 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -76,6 +76,10 @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr)
#define LCR_FEN (1 << 4)
#define LCR_BRK (1 << 0)
+/* Control Register, UARTCR */
+#define CR_TXE (1 << 8)
+#define CR_UARTEN (1 << 0)
+
static const unsigned char pl011_id_arm[8] =
{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
static const unsigned char pl011_id_luminary[8] =
@@ -151,7 +155,12 @@ static inline void pl011_reset_tx_fifo(PL011State *s)
static void pl011_write_txdata(PL011State *s, const uint8_t *buf, int length)
{
- /* ??? Check if transmitter is enabled. */
+ if (!(s->cr & CR_UARTEN)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "PL011 write data but UART disabled\n");
+ }
+ if (!(s->cr & CR_TXE)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "PL011 write data but TX disabled\n");
+ }
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
--
2.38.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 09/11] hw/char/pl011: Check if receiver is enabled
2023-07-10 17:50 [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop Philippe Mathieu-Daudé
` (7 preceding siblings ...)
2023-07-10 17:50 ` [PATCH v2 08/11] hw/char/pl011: Warn when using disabled transmitter Philippe Mathieu-Daudé
@ 2023-07-10 17:51 ` Philippe Mathieu-Daudé
2023-07-14 7:03 ` Richard Henderson
2023-07-10 17:51 ` [PATCH v2 10/11] hw/char/pl011: Rename RX FIFO methods Philippe Mathieu-Daudé
2023-07-10 17:51 ` [RFC PATCH v2 11/11] hw/char/pl011: Implement TX FIFO Philippe Mathieu-Daudé
10 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 17:51 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Philippe Mathieu-Daudé
Do not receive characters when UART or receiver are disabled.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
hw/char/pl011.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 03dce0a1ec..59d239cb83 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -77,6 +77,7 @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr)
#define LCR_BRK (1 << 0)
/* Control Register, UARTCR */
+#define CR_RXE (1 << 9)
#define CR_TXE (1 << 8)
#define CR_UARTEN (1 << 0)
@@ -357,9 +358,11 @@ static void pl011_write(void *opaque, hwaddr offset,
static int pl011_can_receive(void *opaque)
{
PL011State *s = (PL011State *)opaque;
- int r;
+ int r = 0;
- r = s->read_count < pl011_get_fifo_depth(s);
+ if ((s->cr & CR_UARTEN) && (s->cr & CR_RXE)) {
+ r = s->read_count < pl011_get_fifo_depth(s);
+ }
trace_pl011_can_receive(s->lcr, s->read_count, r);
return r;
}
--
2.38.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 10/11] hw/char/pl011: Rename RX FIFO methods
2023-07-10 17:50 [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop Philippe Mathieu-Daudé
` (8 preceding siblings ...)
2023-07-10 17:51 ` [PATCH v2 09/11] hw/char/pl011: Check if receiver is enabled Philippe Mathieu-Daudé
@ 2023-07-10 17:51 ` Philippe Mathieu-Daudé
2023-07-14 7:06 ` Richard Henderson
2023-07-10 17:51 ` [RFC PATCH v2 11/11] hw/char/pl011: Implement TX FIFO Philippe Mathieu-Daudé
10 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 17:51 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Philippe Mathieu-Daudé
In preparation of having a TX FIFO, rename the RX FIFO methods.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
hw/char/pl011.c | 10 +++++-----
hw/char/trace-events | 4 ++--
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 59d239cb83..7c785e7bb0 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -367,7 +367,7 @@ static int pl011_can_receive(void *opaque)
return r;
}
-static void pl011_put_fifo(void *opaque, uint32_t value)
+static void pl011_fifo_rx_put(void *opaque, uint32_t value)
{
PL011State *s = (PL011State *)opaque;
int slot;
@@ -378,9 +378,9 @@ static void pl011_put_fifo(void *opaque, uint32_t value)
s->read_fifo[slot] = value;
s->read_count++;
s->flags &= ~PL011_FLAG_RXFE;
- trace_pl011_put_fifo(value, s->read_count);
+ trace_pl011_fifo_rx_put(value, s->read_count);
if (s->read_count == pipe_depth) {
- trace_pl011_put_fifo_full();
+ trace_pl011_fifo_rx_full();
s->flags |= PL011_FLAG_RXFF;
}
if (s->read_count == s->read_trigger) {
@@ -391,13 +391,13 @@ static void pl011_put_fifo(void *opaque, uint32_t value)
static void pl011_receive(void *opaque, const uint8_t *buf, int size)
{
- pl011_put_fifo(opaque, *buf);
+ pl011_fifo_rx_put(opaque, *buf);
}
static void pl011_event(void *opaque, QEMUChrEvent event)
{
if (event == CHR_EVENT_BREAK) {
- pl011_put_fifo(opaque, DR_BE);
+ pl011_fifo_rx_put(opaque, DR_BE);
}
}
diff --git a/hw/char/trace-events b/hw/char/trace-events
index babf4d35ea..9fd40e3aae 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -58,8 +58,8 @@ pl011_read(uint32_t addr, uint32_t value, const char *regname) "addr 0x%03x valu
pl011_read_fifo(int read_count) "FIFO read, read_count now %d"
pl011_write(uint32_t addr, uint32_t value, const char *regname) "addr 0x%03x value 0x%08x reg %s"
pl011_can_receive(uint32_t lcr, int read_count, int r) "LCR 0x%08x read_count %d returning %d"
-pl011_put_fifo(uint32_t c, int read_count) "new char 0x%x read_count now %d"
-pl011_put_fifo_full(void) "FIFO now full, RXFF set"
+pl011_fifo_rx_put(uint32_t c, int read_count) "new char 0x%02x read_count now %d"
+pl011_fifo_rx_full(void) "RX FIFO now full, RXFF set"
pl011_baudrate_change(unsigned int baudrate, uint64_t clock, uint32_t ibrd, uint32_t fbrd) "new baudrate %u (clk: %" PRIu64 "hz, ibrd: %" PRIu32 ", fbrd: %" PRIu32 ")"
# cmsdk-apb-uart.c
--
2.38.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [RFC PATCH v2 11/11] hw/char/pl011: Implement TX FIFO
2023-07-10 17:50 [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop Philippe Mathieu-Daudé
` (9 preceding siblings ...)
2023-07-10 17:51 ` [PATCH v2 10/11] hw/char/pl011: Rename RX FIFO methods Philippe Mathieu-Daudé
@ 2023-07-10 17:51 ` Philippe Mathieu-Daudé
2023-07-14 7:27 ` Richard Henderson
10 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-07-10 17:51 UTC (permalink / raw)
To: qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Philippe Mathieu-Daudé, Mikko Rapeli
If the UART back-end chardev doesn't drain data as fast as stdout
does or blocks, buffer in the TX FIFO to try again later.
This avoids having the IO-thread busy waiting on chardev back-ends,
reported recently when testing the Trusted Reference Stack and
using the socket backend:
https://linaro.atlassian.net/browse/TRS-149?focusedCommentId=149574
Implement registering a front-end 'watch' callback on back-end
events, so we can resume transmitting when the back-end is writable
again, not blocking the main loop.
Similarly to the RX FIFO path, FIFO level selection is not
implemented (interrupt is triggered when a single byte is available
in the FIFO).
We only migrate the TX FIFO if it is in use.
Reported-by: Mikko Rapeli <mikko.rapeli@linaro.org>
Suggested-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
RFC: Again for the migration part.
---
include/hw/char/pl011.h | 2 +
hw/char/pl011.c | 108 ++++++++++++++++++++++++++++++++++++++--
hw/char/trace-events | 4 ++
3 files changed, 109 insertions(+), 5 deletions(-)
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
index d853802132..20898f43a6 100644
--- a/include/hw/char/pl011.h
+++ b/include/hw/char/pl011.h
@@ -18,6 +18,7 @@
#include "hw/sysbus.h"
#include "chardev/char-fe.h"
#include "qom/object.h"
+#include "qemu/fifo8.h"
#define TYPE_PL011 "pl011"
OBJECT_DECLARE_SIMPLE_TYPE(PL011State, PL011)
@@ -53,6 +54,7 @@ struct PL011State {
Clock *clk;
bool migrate_clk;
const unsigned char *id;
+ Fifo8 xmit_fifo;
};
DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr);
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 7c785e7bb0..4392773327 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -57,6 +57,9 @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr)
/* Data Register, UARTDR */
#define DR_BE (1 << 10)
+/* Receive Status Register/Error Clear Register, UARTRSR/UARTECR */
+#define RSR_OE (1 << 3)
+
/* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */
#define INT_OE (1 << 10)
#define INT_BE (1 << 9)
@@ -152,6 +155,59 @@ static inline void pl011_reset_tx_fifo(PL011State *s)
/* Reset FIFO flags */
s->flags &= ~PL011_FLAG_TXFF;
s->flags |= PL011_FLAG_TXFE;
+
+ fifo8_reset(&s->xmit_fifo);
+}
+
+static gboolean pl011_drain_tx(PL011State *s)
+{
+ trace_pl011_fifo_tx_drain(fifo8_num_used(&s->xmit_fifo));
+ pl011_reset_tx_fifo(s);
+ s->rsr &= ~RSR_OE;
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean pl011_xmit(void *do_not_use, GIOCondition cond, void *opaque)
+{
+ PL011State *s = opaque;
+ int ret;
+ const uint8_t *buf;
+ uint32_t buflen;
+ uint32_t count;
+ bool tx_enabled;
+
+ if (!qemu_chr_fe_backend_connected(&s->chr)) {
+ /* Instant drain the fifo when there's no back-end */
+ return pl011_drain_tx(s);
+ }
+
+ tx_enabled = s->cr & CR_UARTEN;
+ /* Allow completing the current FIFO character before stopping. */
+ count = tx_enabled ? fifo8_num_used(&s->xmit_fifo) : 1; /* current only */
+ if (count) {
+ /* Transmit as much data as we can */
+ buf = fifo8_peek_buf(&s->xmit_fifo, count, &buflen);
+ ret = qemu_chr_fe_write(&s->chr, buf, buflen);
+ if (ret >= 0) {
+ /* Pop the data we could transmit */
+ trace_pl011_fifo_tx_xmit(ret);
+ fifo8_pop_buf(&s->xmit_fifo, ret, NULL);
+ s->int_level |= INT_TX;
+ }
+
+ if (tx_enabled && !fifo8_is_empty(&s->xmit_fifo)) {
+ /* Reschedule another transmission if we couldn't transmit all */
+ guint r = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
+ pl011_xmit, s);
+ if (!r) {
+ return pl011_drain_tx(s);
+ }
+ }
+
+ pl011_update(s);
+ }
+
+ return G_SOURCE_REMOVE;
}
static void pl011_write_txdata(PL011State *s, const uint8_t *buf, int length)
@@ -162,12 +218,32 @@ static void pl011_write_txdata(PL011State *s, const uint8_t *buf, int length)
if (!(s->cr & CR_TXE)) {
qemu_log_mask(LOG_GUEST_ERROR, "PL011 write data but TX disabled\n");
}
+ if (!fifo8_is_empty(&s->xmit_fifo)) {
+ /*
+ * If the UART is disabled in the middle of transmission
+ * or reception, it completes the current character before
+ * stopping.
+ */
+ pl011_xmit(NULL, G_IO_OUT, s);
+ return;
+ }
- /* 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, 1);
- s->int_level |= INT_TX;
- pl011_update(s);
+ if (length > fifo8_num_free(&s->xmit_fifo)) {
+ /*
+ * The FIFO contents remain valid because no more data is
+ * written when the FIFO is full, only the contents of the
+ * shift register are overwritten. The CPU must now read
+ * the data, to empty the FIFO.
+ */
+ trace_pl011_fifo_tx_overrun();
+ s->rsr |= RSR_OE;
+ return;
+ }
+
+ trace_pl011_fifo_tx_put(length);
+ fifo8_push_all(&s->xmit_fifo, buf, length);
+
+ pl011_xmit(NULL, G_IO_OUT, s);
}
static uint32_t pl011_read_rxdata(PL011State *s)
@@ -434,6 +510,13 @@ static const VMStateDescription vmstate_pl011_clock = {
}
};
+static bool pl011_xmit_fifo_state_needed(void *opaque, int version_id)
+{
+ PL011State* s = opaque;
+
+ return pl011_is_fifo_enabled(s) && !fifo8_is_empty(&s->xmit_fifo);
+}
+
static int pl011_post_load(void *opaque, int version_id)
{
PL011State* s = opaque;
@@ -455,6 +538,11 @@ static int pl011_post_load(void *opaque, int version_id)
s->read_pos = 0;
}
+ if (pl011_xmit_fifo_state_needed(s, version_id)) {
+ /* Reschedule another transmission */
+ qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP, pl011_xmit, s);
+ }
+
return 0;
}
@@ -473,6 +561,7 @@ static const VMStateDescription vmstate_pl011 = {
VMSTATE_UINT32(int_enabled, PL011State),
VMSTATE_UINT32(int_level, PL011State),
VMSTATE_UINT32_ARRAY(read_fifo, PL011State, PL011_FIFO_DEPTH),
+ VMSTATE_FIFO8_TEST(xmit_fifo, PL011State, pl011_xmit_fifo_state_needed),
VMSTATE_UINT32(ilpr, PL011State),
VMSTATE_UINT32(ibrd, PL011State),
VMSTATE_UINT32(fbrd, PL011State),
@@ -500,6 +589,7 @@ static void pl011_init(Object *obj)
PL011State *s = PL011(obj);
int i;
+ fifo8_create(&s->xmit_fifo, PL011_FIFO_DEPTH);
memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
@@ -512,6 +602,13 @@ static void pl011_init(Object *obj)
s->id = pl011_id_arm;
}
+static void pl011_finalize(Object *obj)
+{
+ PL011State *s = PL011(obj);
+
+ fifo8_destroy(&s->xmit_fifo);
+}
+
static void pl011_realize(DeviceState *dev, Error **errp)
{
PL011State *s = PL011(dev);
@@ -555,6 +652,7 @@ static const TypeInfo pl011_arm_info = {
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PL011State),
.instance_init = pl011_init,
+ .instance_finalize = pl011_finalize,
.class_init = pl011_class_init,
};
diff --git a/hw/char/trace-events b/hw/char/trace-events
index 9fd40e3aae..4c25564066 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -60,6 +60,10 @@ pl011_write(uint32_t addr, uint32_t value, const char *regname) "addr 0x%03x val
pl011_can_receive(uint32_t lcr, int read_count, int r) "LCR 0x%08x read_count %d returning %d"
pl011_fifo_rx_put(uint32_t c, int read_count) "new char 0x%02x read_count now %d"
pl011_fifo_rx_full(void) "RX FIFO now full, RXFF set"
+pl011_fifo_tx_put(int count) "TX FIFO push %d"
+pl011_fifo_tx_xmit(int count) "TX FIFO pop %d"
+pl011_fifo_tx_overrun(void) "TX FIFO overrun"
+pl011_fifo_tx_drain(unsigned drained) "TX FIFO draining %u"
pl011_baudrate_change(unsigned int baudrate, uint64_t clock, uint32_t ibrd, uint32_t fbrd) "new baudrate %u (clk: %" PRIu64 "hz, ibrd: %" PRIu32 ", fbrd: %" PRIu32 ")"
# cmsdk-apb-uart.c
--
2.38.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH v2 01/11] hw/char/pl011: Restrict MemoryRegionOps implementation access sizes
2023-07-10 17:50 ` [PATCH v2 01/11] hw/char/pl011: Restrict MemoryRegionOps implementation access sizes Philippe Mathieu-Daudé
@ 2023-07-14 6:47 ` Richard Henderson
0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2023-07-14 6:47 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm
On 7/10/23 18:50, Philippe Mathieu-Daudé wrote:
> The pl011_read() and pl011_write() handlers shift the offset
> argument by 2, so are implemented on a 32-bit boundary.
>
> Signed-off-by: Philippe Mathieu-Daudé<philmd@linaro.org>
> ---
> hw/char/pl011.c | 2 ++
> 1 file changed, 2 insertions(+)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 02/11] hw/char/pl011: Display register name in trace events
2023-07-10 17:50 ` [PATCH v2 02/11] hw/char/pl011: Display register name in trace events Philippe Mathieu-Daudé
@ 2023-07-14 6:49 ` Richard Henderson
0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2023-07-14 6:49 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm
On 7/10/23 18:50, Philippe Mathieu-Daudé wrote:
> To avoid knowing the register addresses by heart,
> display their name along in the trace events.
>
> Since the MMIO region is 4K wide (0x1000 bytes),
> displaying the address with 3 digits is enough,
> so reduce the address format.
>
> Signed-off-by: Philippe Mathieu-Daudé<philmd@linaro.org>
> Reviewed-by: Alex Bennée<alex.bennee@linaro.org>
> ---
> hw/char/pl011.c | 25 ++++++++++++++++++++++---
> hw/char/trace-events | 4 ++--
> 2 files changed, 24 insertions(+), 5 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 03/11] hw/char/pl011: Remove duplicated PL011_INT_[RT]X definitions
2023-07-10 17:50 ` [PATCH v2 03/11] hw/char/pl011: Remove duplicated PL011_INT_[RT]X definitions Philippe Mathieu-Daudé
@ 2023-07-14 6:50 ` Richard Henderson
0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2023-07-14 6:50 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm
On 7/10/23 18:50, Philippe Mathieu-Daudé wrote:
> PL011_INT_TX duplicates INT_TX, and PL011_INT_RX INT_RX.
> Follow other register fields definitions from this file,
> keep the shorter form.
>
> Signed-off-by: Philippe Mathieu-Daudé<philmd@linaro.org>
> Reviewed-by: Alex Bennée<alex.bennee@linaro.org>
> ---
> hw/char/pl011.c | 9 +++------
> 1 file changed, 3 insertions(+), 6 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 04/11] hw/char/pl011: Replace magic values by register field definitions
2023-07-10 17:50 ` [PATCH v2 04/11] hw/char/pl011: Replace magic values by register field definitions Philippe Mathieu-Daudé
@ 2023-07-14 6:54 ` Richard Henderson
0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2023-07-14 6:54 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm
On 7/10/23 18:50, Philippe Mathieu-Daudé wrote:
> 0x400 is Data Register Break Error (DR_BE),
> 0x10 is Line Control Register Fifo Enabled (LCR_FEN)
> and 0x1 is Send Break (LCR_BRK).
>
> Signed-off-by: Philippe Mathieu-Daudé<philmd@linaro.org>
> Reviewed-by: Alex Bennée<alex.bennee@linaro.org>
> ---
> hw/char/pl011.c | 22 +++++++++++++++-------
> 1 file changed, 15 insertions(+), 7 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 05/11] hw/char/pl011: Split RX/TX path of pl011_reset_fifo()
2023-07-10 17:50 ` [PATCH v2 05/11] hw/char/pl011: Split RX/TX path of pl011_reset_fifo() Philippe Mathieu-Daudé
@ 2023-07-14 6:56 ` Richard Henderson
0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2023-07-14 6:56 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm
On 7/10/23 18:50, Philippe Mathieu-Daudé wrote:
> To be able to reset the RX or TX FIFO separately,
> split pl011_reset_fifo() in two.
>
> Signed-off-by: Philippe Mathieu-Daudé<philmd@linaro.org>
> Reviewed-by: Alex Bennée<alex.bennee@linaro.org>
> ---
> hw/char/pl011.c | 19 ++++++++++++++-----
> 1 file changed, 14 insertions(+), 5 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 06/11] hw/char/pl011: Extract pl011_write_txdata() from pl011_write()
2023-07-10 17:50 ` [PATCH v2 06/11] hw/char/pl011: Extract pl011_write_txdata() from pl011_write() Philippe Mathieu-Daudé
@ 2023-07-14 6:58 ` Richard Henderson
2023-10-12 13:07 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2023-07-14 6:58 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm
On 7/10/23 18:50, Philippe Mathieu-Daudé wrote:
> +static void pl011_write_txdata(PL011State *s, const uint8_t *buf, int length)
> +{
> + /* ??? Check if transmitter is enabled. */
> +
> + /* 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, 1);
Not using length?
> + pl011_write_txdata(s, (uint8_t *) &value, 1);
Host endianness error. Copy to local uint8_t first.
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 07/11] hw/char/pl011: Extract pl011_read_rxdata() from pl011_read()
2023-07-10 17:50 ` [PATCH v2 07/11] hw/char/pl011: Extract pl011_read_rxdata() from pl011_read() Philippe Mathieu-Daudé
@ 2023-07-14 7:00 ` Richard Henderson
0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2023-07-14 7:00 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm
On 7/10/23 18:50, Philippe Mathieu-Daudé wrote:
> + if (s->read_count == s->read_trigger - 1)
> + s->int_level &= ~ INT_RX;
Fix the braces. Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 08/11] hw/char/pl011: Warn when using disabled transmitter
2023-07-10 17:50 ` [PATCH v2 08/11] hw/char/pl011: Warn when using disabled transmitter Philippe Mathieu-Daudé
@ 2023-07-14 7:01 ` Richard Henderson
0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2023-07-14 7:01 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm
On 7/10/23 18:50, Philippe Mathieu-Daudé wrote:
> We shouldn't transmit characters when the full UART or its
> transmitter is disabled. However we don't want to break the
> possibly incomplete "my first bare metal assembly program"s,
> so we choose to simply display a warning when this occurs.
>
> Signed-off-by: Philippe Mathieu-Daudé<philmd@linaro.org>
> Reviewed-by: Alex Bennée<alex.bennee@linaro.org>
> ---
> hw/char/pl011.c | 11 ++++++++++-
> 1 file changed, 10 insertions(+), 1 deletion(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 09/11] hw/char/pl011: Check if receiver is enabled
2023-07-10 17:51 ` [PATCH v2 09/11] hw/char/pl011: Check if receiver is enabled Philippe Mathieu-Daudé
@ 2023-07-14 7:03 ` Richard Henderson
0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2023-07-14 7:03 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm
On 7/10/23 18:51, Philippe Mathieu-Daudé wrote:
> Do not receive characters when UART or receiver are disabled.
>
> Signed-off-by: Philippe Mathieu-Daudé<philmd@linaro.org>
> ---
> hw/char/pl011.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
I guess this doesn't fall under "my first assembly program" because it isn't part of
"Hello, World"?
Anyway, for real stuffz:
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 10/11] hw/char/pl011: Rename RX FIFO methods
2023-07-10 17:51 ` [PATCH v2 10/11] hw/char/pl011: Rename RX FIFO methods Philippe Mathieu-Daudé
@ 2023-07-14 7:06 ` Richard Henderson
0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2023-07-14 7:06 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm
On 7/10/23 18:51, Philippe Mathieu-Daudé wrote:
> In preparation of having a TX FIFO, rename the RX FIFO methods.
>
> Signed-off-by: Philippe Mathieu-Daudé<philmd@linaro.org>
> Reviewed-by: Alex Bennée<alex.bennee@linaro.org>
> ---
> hw/char/pl011.c | 10 +++++-----
> hw/char/trace-events | 4 ++--
> 2 files changed, 7 insertions(+), 7 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC PATCH v2 11/11] hw/char/pl011: Implement TX FIFO
2023-07-10 17:51 ` [RFC PATCH v2 11/11] hw/char/pl011: Implement TX FIFO Philippe Mathieu-Daudé
@ 2023-07-14 7:27 ` Richard Henderson
2023-10-13 14:05 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2023-07-14 7:27 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Mikko Rapeli
On 7/10/23 18:51, Philippe Mathieu-Daudé wrote:
> +static gboolean pl011_xmit(void *do_not_use, GIOCondition cond, void *opaque)
> +{
> + PL011State *s = opaque;
> + int ret;
> + const uint8_t *buf;
> + uint32_t buflen;
> + uint32_t count;
> + bool tx_enabled;
> +
> + if (!qemu_chr_fe_backend_connected(&s->chr)) {
> + /* Instant drain the fifo when there's no back-end */
> + return pl011_drain_tx(s);
> + }
> +
> + tx_enabled = s->cr & CR_UARTEN;
What happened to "Hello, World"? We ought to be consistent.
For actual modeling, I think you need TXE too.
Where does UARTFR get updated after successfully transmitting data?
> static void pl011_write_txdata(PL011State *s, const uint8_t *buf, int length)
> @@ -162,12 +218,32 @@ static void pl011_write_txdata(PL011State *s, const uint8_t *buf, int length)
> if (!(s->cr & CR_TXE)) {
> qemu_log_mask(LOG_GUEST_ERROR, "PL011 write data but TX disabled\n");
> }
> + if (!fifo8_is_empty(&s->xmit_fifo)) {
> + /*
> + * If the UART is disabled in the middle of transmission
> + * or reception, it completes the current character before
> + * stopping.
> + */
> + pl011_xmit(NULL, G_IO_OUT, s);
> + return;
> + }
Why is this in write_txdata? I would expect to find this with a write to UARTCR.
You appear to *not* be queuing data unless the fifo is empty.
> + if (length > fifo8_num_free(&s->xmit_fifo)) {
> + /*
> + * The FIFO contents remain valid because no more data is
> + * written when the FIFO is full, only the contents of the
> + * shift register are overwritten. The CPU must now read
> + * the data, to empty the FIFO.
> + */
> + trace_pl011_fifo_tx_overrun();
> + s->rsr |= RSR_OE;
> + return;
> + }
> +
> + trace_pl011_fifo_tx_put(length);
> + fifo8_push_all(&s->xmit_fifo, buf, length);
Since length will always be 1, probably we should just remove it.
> +static bool pl011_xmit_fifo_state_needed(void *opaque, int version_id)
> +{
> + PL011State* s = opaque;
> +
> + return pl011_is_fifo_enabled(s) && !fifo8_is_empty(&s->xmit_fifo);
> +}
Ok.
> static int pl011_post_load(void *opaque, int version_id)
> {
> PL011State* s = opaque;
> @@ -455,6 +538,11 @@ static int pl011_post_load(void *opaque, int version_id)
> s->read_pos = 0;
> }
>
> + if (pl011_xmit_fifo_state_needed(s, version_id)) {
> + /* Reschedule another transmission */
> + qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP, pl011_xmit, s);
> + }
Ok.
> @@ -473,6 +561,7 @@ static const VMStateDescription vmstate_pl011 = {
> VMSTATE_UINT32(int_enabled, PL011State),
> VMSTATE_UINT32(int_level, PL011State),
> VMSTATE_UINT32_ARRAY(read_fifo, PL011State, PL011_FIFO_DEPTH),
> + VMSTATE_FIFO8_TEST(xmit_fifo, PL011State, pl011_xmit_fifo_state_needed),
Not ok.
The new data should go in its own VMStateDescription, like vmstate_pl011_clock.
r~
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 06/11] hw/char/pl011: Extract pl011_write_txdata() from pl011_write()
2023-07-14 6:58 ` Richard Henderson
@ 2023-10-12 13:07 ` Philippe Mathieu-Daudé
2023-10-12 14:25 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-12 13:07 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm
On 14/7/23 08:58, Richard Henderson wrote:
> On 7/10/23 18:50, Philippe Mathieu-Daudé wrote:
>> +static void pl011_write_txdata(PL011State *s, const uint8_t *buf, int
>> length)
>> +{
>> + /* ??? Check if transmitter is enabled. */
>> +
>> + /* 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, 1);
>
> Not using length?
This is a simple "code extract" patch. Length is used when
we switch to FIFO in the last patch.
>> + pl011_write_txdata(s, (uint8_t *) &value, 1);
>
> Host endianness error. Copy to local uint8_t first.
Oops, good catch, thanks.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 06/11] hw/char/pl011: Extract pl011_write_txdata() from pl011_write()
2023-10-12 13:07 ` Philippe Mathieu-Daudé
@ 2023-10-12 14:25 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-12 14:25 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm
On 12/10/23 15:07, Philippe Mathieu-Daudé wrote:
> On 14/7/23 08:58, Richard Henderson wrote:
>> On 7/10/23 18:50, Philippe Mathieu-Daudé wrote:
>>> +static void pl011_write_txdata(PL011State *s, const uint8_t *buf,
>>> int length)
>>> +{
>>> + /* ??? Check if transmitter is enabled. */
>>> +
>>> + /* 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, 1);
>>
>> Not using length?
>
> This is a simple "code extract" patch. Length is used when
> we switch to FIFO in the last patch.
Hmm you are right it isn't used...
The UARTDR register is 16-bit wide. Only 8 bits are used for data.
No need for a 'length' param here.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [RFC PATCH v2 11/11] hw/char/pl011: Implement TX FIFO
2023-07-14 7:27 ` Richard Henderson
@ 2023-10-13 14:05 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 26+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-13 14:05 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
Cc: Marc-André Lureau, Peter Maydell, Evgeny Iakovlev,
Alex Bennée, Gavin Shan, Paolo Bonzini, qemu-arm,
Mikko Rapeli
On 14/7/23 09:27, Richard Henderson wrote:
> On 7/10/23 18:51, Philippe Mathieu-Daudé wrote:
>> +static gboolean pl011_xmit(void *do_not_use, GIOCondition cond, void
>> *opaque)
>> +{
>> + PL011State *s = opaque;
>> + int ret;
>> + const uint8_t *buf;
>> + uint32_t buflen;
>> + uint32_t count;
>> + bool tx_enabled;
>> +
>> + if (!qemu_chr_fe_backend_connected(&s->chr)) {
>> + /* Instant drain the fifo when there's no back-end */
>> + return pl011_drain_tx(s);
>> + }
>> +
>> + tx_enabled = s->cr & CR_UARTEN;
>
> What happened to "Hello, World"? We ought to be consistent.
What do you mean?
> For actual modeling, I think you need TXE too.
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2023-10-13 14:06 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-10 17:50 [PATCH v2 00/11] hw/char/pl011: Implement TX (async) FIFO to avoid blocking the main loop Philippe Mathieu-Daudé
2023-07-10 17:50 ` [PATCH v2 01/11] hw/char/pl011: Restrict MemoryRegionOps implementation access sizes Philippe Mathieu-Daudé
2023-07-14 6:47 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 02/11] hw/char/pl011: Display register name in trace events Philippe Mathieu-Daudé
2023-07-14 6:49 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 03/11] hw/char/pl011: Remove duplicated PL011_INT_[RT]X definitions Philippe Mathieu-Daudé
2023-07-14 6:50 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 04/11] hw/char/pl011: Replace magic values by register field definitions Philippe Mathieu-Daudé
2023-07-14 6:54 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 05/11] hw/char/pl011: Split RX/TX path of pl011_reset_fifo() Philippe Mathieu-Daudé
2023-07-14 6:56 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 06/11] hw/char/pl011: Extract pl011_write_txdata() from pl011_write() Philippe Mathieu-Daudé
2023-07-14 6:58 ` Richard Henderson
2023-10-12 13:07 ` Philippe Mathieu-Daudé
2023-10-12 14:25 ` Philippe Mathieu-Daudé
2023-07-10 17:50 ` [PATCH v2 07/11] hw/char/pl011: Extract pl011_read_rxdata() from pl011_read() Philippe Mathieu-Daudé
2023-07-14 7:00 ` Richard Henderson
2023-07-10 17:50 ` [PATCH v2 08/11] hw/char/pl011: Warn when using disabled transmitter Philippe Mathieu-Daudé
2023-07-14 7:01 ` Richard Henderson
2023-07-10 17:51 ` [PATCH v2 09/11] hw/char/pl011: Check if receiver is enabled Philippe Mathieu-Daudé
2023-07-14 7:03 ` Richard Henderson
2023-07-10 17:51 ` [PATCH v2 10/11] hw/char/pl011: Rename RX FIFO methods Philippe Mathieu-Daudé
2023-07-14 7:06 ` Richard Henderson
2023-07-10 17:51 ` [RFC PATCH v2 11/11] hw/char/pl011: Implement TX FIFO Philippe Mathieu-Daudé
2023-07-14 7:27 ` Richard Henderson
2023-10-13 14:05 ` Philippe Mathieu-Daudé
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).