[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 43/48] hw/char/pl011: add a clock input
From: |
Peter Maydell |
Subject: |
[PULL 43/48] hw/char/pl011: add a clock input |
Date: |
Tue, 27 Oct 2020 11:44:33 +0000 |
From: Luc Michel <luc@lmichel.fr>
Add a clock input to the PL011 UART so we can compute the current baud
rate and trace it. This is intended for developers who wish to use QEMU
to e.g. debug their firmware or to figure out the baud rate configured
by an unknown/closed source binary.
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Luc Michel <luc@lmichel.fr>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
include/hw/char/pl011.h | 1 +
hw/char/pl011.c | 45 +++++++++++++++++++++++++++++++++++++++++
hw/char/trace-events | 1 +
3 files changed, 47 insertions(+)
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
index a91ea50e11b..33e5e5317b8 100644
--- a/include/hw/char/pl011.h
+++ b/include/hw/char/pl011.h
@@ -49,6 +49,7 @@ struct PL011State {
int read_trigger;
CharBackend chr;
qemu_irq irq[6];
+ Clock *clk;
const unsigned char *id;
};
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index 13e784f9d90..ede16c781c9 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -22,6 +22,7 @@
#include "hw/char/pl011.h"
#include "hw/irq.h"
#include "hw/sysbus.h"
+#include "hw/qdev-clock.h"
#include "migration/vmstate.h"
#include "chardev/char-fe.h"
#include "qemu/log.h"
@@ -169,6 +170,25 @@ static void pl011_set_read_trigger(PL011State *s)
s->read_trigger = 1;
}
+static unsigned int pl011_get_baudrate(const PL011State *s)
+{
+ uint64_t clk;
+
+ if (s->fbrd == 0) {
+ return 0;
+ }
+
+ clk = clock_get_hz(s->clk);
+ return (clk / ((s->ibrd << 6) + s->fbrd)) << 2;
+}
+
+static void pl011_trace_baudrate_change(const PL011State *s)
+{
+ trace_pl011_baudrate_change(pl011_get_baudrate(s),
+ clock_get_hz(s->clk),
+ s->ibrd, s->fbrd);
+}
+
static void pl011_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
@@ -198,9 +218,11 @@ static void pl011_write(void *opaque, hwaddr offset,
break;
case 9: /* UARTIBRD */
s->ibrd = value;
+ pl011_trace_baudrate_change(s);
break;
case 10: /* UARTFBRD */
s->fbrd = value;
+ pl011_trace_baudrate_change(s);
break;
case 11: /* UARTLCR_H */
/* Reset the FIFO state on FIFO enable or disable */
@@ -286,12 +308,29 @@ static void pl011_event(void *opaque, QEMUChrEvent event)
pl011_put_fifo(opaque, 0x400);
}
+static void pl011_clock_update(void *opaque)
+{
+ PL011State *s = PL011(opaque);
+
+ pl011_trace_baudrate_change(s);
+}
+
static const MemoryRegionOps pl011_ops = {
.read = pl011_read,
.write = pl011_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
+static const VMStateDescription vmstate_pl011_clock = {
+ .name = "pl011/clock",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_CLOCK(clk, PL011State),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_pl011 = {
.name = "pl011",
.version_id = 2,
@@ -314,6 +353,10 @@ static const VMStateDescription vmstate_pl011 = {
VMSTATE_INT32(read_count, PL011State),
VMSTATE_INT32(read_trigger, PL011State),
VMSTATE_END_OF_LIST()
+ },
+ .subsections = (const VMStateDescription * []) {
+ &vmstate_pl011_clock,
+ NULL
}
};
@@ -334,6 +377,8 @@ static void pl011_init(Object *obj)
sysbus_init_irq(sbd, &s->irq[i]);
}
+ s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s);
+
s->read_trigger = 1;
s->ifl = 0x12;
s->cr = 0x300;
diff --git a/hw/char/trace-events b/hw/char/trace-events
index 609df10fed4..81026f66127 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -65,6 +65,7 @@ pl011_write(uint32_t addr, uint32_t value) "addr 0x%08x value
0x%08x"
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_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
cmsdk_apb_uart_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB
UART read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
--
2.20.1
- [PULL 34/48] hw/arm/raspi: add a skeleton implementation of the CPRMAN, (continued)
- [PULL 34/48] hw/arm/raspi: add a skeleton implementation of the CPRMAN, Peter Maydell, 2020/10/27
- [PULL 35/48] hw/misc/bcm2835_cprman: add a PLL skeleton implementation, Peter Maydell, 2020/10/27
- [PULL 36/48] hw/misc/bcm2835_cprman: implement PLLs behaviour, Peter Maydell, 2020/10/27
- [PULL 37/48] hw/misc/bcm2835_cprman: add a PLL channel skeleton implementation, Peter Maydell, 2020/10/27
- [PULL 38/48] hw/misc/bcm2835_cprman: implement PLL channels behaviour, Peter Maydell, 2020/10/27
- [PULL 39/48] hw/misc/bcm2835_cprman: add a clock mux skeleton implementation, Peter Maydell, 2020/10/27
- [PULL 42/48] hw/misc/bcm2835_cprman: add sane reset values to the registers, Peter Maydell, 2020/10/27
- [PULL 40/48] hw/misc/bcm2835_cprman: implement clock mux behaviour, Peter Maydell, 2020/10/27
- [PULL 41/48] hw/misc/bcm2835_cprman: add the DSI0HSCK multiplexer, Peter Maydell, 2020/10/27
- [PULL 44/48] hw/arm/bcm2835_peripherals: connect the UART clock, Peter Maydell, 2020/10/27
- [PULL 43/48] hw/char/pl011: add a clock input,
Peter Maydell <=
- [PULL 46/48] hw/arm/sbsa-ref: add SBSA watchdog device, Peter Maydell, 2020/10/27
- [PULL 45/48] hw/watchdog: Implement SBSA watchdog device, Peter Maydell, 2020/10/27
- [PULL 48/48] hw/timer/armv7m_systick: Rewrite to use ptimers, Peter Maydell, 2020/10/27
- [PULL 47/48] hw/core/ptimer: Support ptimer being disabled by timer callback, Peter Maydell, 2020/10/27
- Re: [PULL 00/48] target-arm queue, no-reply, 2020/10/27
- Re: [PULL 00/48] target-arm queue, Peter Maydell, 2020/10/29