Skip to content

Commit 2d00aab

Browse files
lauraltalexandruag
authored andcommitted
improve documentation for serial console
Signed-off-by: Laura Loghin <[email protected]>
1 parent 9d04e75 commit 2d00aab

File tree

2 files changed

+27
-19
lines changed

2 files changed

+27
-19
lines changed

README.md

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,30 @@ this support only for the
99

1010
### Design
1111

12-
The console emulation is done by emulating a hybrid between
13-
[UART 8250 serial port](https://en.wikibooks.org/w/index.php?title=Serial_Programming/8250_UART_Programming&section=15#Serial_COM_Port_Memory_and_I/O_Allocation)
14-
and [UART 16550 serial port](https://en.wikipedia.org/wiki/16550_UART).
12+
The console emulation is done by emulating a simple
13+
[UART 16550A serial port](https://en.wikipedia.org/wiki/16550_UART).
14+
This UART is an improvement of the original
15+
[UART 8250 serial port](https://en.wikibooks.org/w/index.php?title=Serial_Programming/8250_UART_Programming&section=15#Serial_COM_Port_Memory_and_I/O_Allocation),
16+
mostly because of the FIFO buffers that allow storing more than one byte at a
17+
time, which, in virtualized environments, is essential.
1518
For a VMM to be able to use this device, besides the emulation part which is
1619
covered in this crate, the serial port should be added to the microVM’s PIO bus,
1720
the serial backend should be defined and if and how the event handling is done.
1821

1922
The following UART registers are emulated via the
2023
[`Serial` structure](src/serial.rs): DLL, IER, DLH, IIR, LCR, LSR, MCR, MSR and
21-
SR (more details about these,
22-
[here](http://%20https//en.wikibooks.org/w/index.php?title=Serial_Programming/8250_UART_Programming%C2%A7ion=15#UART_Registers)).
24+
SR (a brief, but nice presentation about these,
25+
[here](https://www.lammertbies.nl/comm/info/serial-uart#regs)).
2326
The Fifo Control Register (FCR) is not emulated since we are not interested in
24-
directly controlling the FIFOs and The Receiver Buffer and Transmitter Holding
25-
Buffer registers (THR and RBR) functionality is simplified, yet extended by
26-
using a single buffer. This buffer helps in testing the UART when running in
27-
loopback mode and for keeping the guest output to a `Write` object (`out`).
28-
The VMM that will use the serial console, when instantiating a `Serial`, will
29-
have to provide a `Write` object for it (for example `io::Stdout` or
30-
`io::Sink`).
27+
directly controlling the FIFOs (which, in our case, are always enabled) and
28+
The Receiver Buffer and Transmitter Holding Buffer registers (THR and RBR)
29+
functionality is simplified, yet extended by using a single FIFO buffer. When
30+
reading from RBR, the oldest unread byte from the FIFO is returned and when
31+
writing to THR, the FIFO buffer is extended with the new byte. This buffer helps
32+
in testing the UART when running in loopback mode and for keeping the guest
33+
output to a `Write` object (`out`). The VMM that will use the serial console,
34+
when instantiating a `Serial`, will have to provide a `Write` object for it (for
35+
example `io::Stdout` or `io::Sink`).
3136
The `interrupt_evt` fd is the currently used mechanism for notifying the driver
3237
when changes in the previously mentioned buffer happened that need to be
3338
handled, but further abstractions may come here; see

src/serial.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ const LCR_DLAB_BIT: u8 = 0b1000_0000;
5151
const LSR_DATA_READY_BIT: u8 = 0b0000_0001;
5252
// These two bits help the driver know if the device is ready to accept
5353
// another character.
54+
// THR is empty.
5455
const LSR_EMPTY_THR_BIT: u8 = 0b0010_0000;
56+
// The shift register, which takes a byte from THR and breaks it in bits
57+
// for sending them on the line, is empty.
5558
const LSR_IDLE_BIT: u8 = 0b0100_0000;
5659

5760
// The following five MCR bits allow direct manipulation of the device and
@@ -84,9 +87,9 @@ const DEFAULT_BAUD_DIVISOR_LOW: u8 = 0x0C;
8487
const DEFAULT_INTERRUPT_ENABLE: u8 = 0x00;
8588
// No pending interrupt.
8689
const DEFAULT_INTERRUPT_IDENTIFICATION: u8 = IIR_NONE_BIT;
87-
// We're setting the default to include LSR_EMPTY_THR_BIT and never update
88-
// that bit because we're working with a virtual device, hence we should
89-
// always be ready to receive more data.
90+
// We're setting the default to include LSR_EMPTY_THR_BIT and LSR_IDLE_BIT
91+
// and never update those bits because we're working with a virtual device,
92+
// hence we should always be ready to receive more data.
9093
const DEFAULT_LINE_STATUS: u8 = LSR_EMPTY_THR_BIT | LSR_IDLE_BIT;
9194
// 8 bits word length.
9295
const DEFAULT_LINE_CONTROL: u8 = 0b0000_0011;
@@ -114,10 +117,10 @@ pub struct Serial<W: Write> {
114117
modem_control: u8,
115118
modem_status: u8,
116119
scratch: u8,
117-
// A simplified way to achieve (and extend) the Receiver and Transmitter
118-
// registers functionality. It is worth mentioning these registers can
119-
// store only one byte when having in mind the UART specification, but we
120-
// are somehow simulating here the FIFO capability too.
120+
// This is the buffer, that is used for achieving the Receiver and Transmitter
121+
// registers functionality in FIFO mode. Reading from RBR will return the oldest
122+
// unread byte from the buffer and writing to THR will expand this buffer with
123+
// one byte.
121124
in_buffer: VecDeque<u8>,
122125

123126
// Used for notifying the driver about some in/out events.

0 commit comments

Comments
 (0)