serial.rs87.33%
1
// Copyright 2024 Google LLC2
//3
// Licensed under the Apache License, Version 2.0 (the "License");4
// you may not use this file except in compliance with the License.5
// You may obtain a copy of the License at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// distributed under the License is distributed on an "AS IS" BASIS,11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12
// See the License for the specific language governing permissions and13
// limitations under the License.14
15
use std::collections::VecDeque;16
use std::io::{Read, Write};17
use std::sync::Arc;18
19
use bitfield::bitfield;20
use parking_lot::Mutex;21
22
use crate::device::console::{Console, ConsoleThread, UartRecv};23
use crate::device::ioapic::IoApic;24
use crate::device::{self, MmioDev, Pause, Result};25
use crate::hv::MsiSender;26
use crate::mem::emulated::{Action, Mmio};27
use crate::{bitflags, mem};28
29
const TX_HOLDING_REGISTER: u16 = 0x0;30
const RX_BUFFER_REGISTER: u16 = 0x0;31
const DIVISOR_LATCH_LSB: u16 = 0x0;32
const DIVISOR_LATCH_MSB: u16 = 0x1;33
const INTERRUPT_ENABLE_REGISTER: u16 = 0x1;34
const FIFO_CONTROL_REGISTER: u16 = 0x2;35
const INTERRUPT_IDENTIFICATION_REGISTER: u16 = 0x2;36
const LINE_CONTROL_REGISTER: u16 = 0x3;37
const MODEM_CONTROL_REGISTER: u16 = 0x4;38
const LINE_STATUS_REGISTER: u16 = 0x5;39
const MODEM_STATUS_REGISTER: u16 = 0x6;40
const SCRATCH_REGISTER: u16 = 0x7;41
42
// offset 0x1, Interrupt Enable Register (IER)43
bitflags! {44
#[derive(Default)]45
pub struct InterruptEnable(u8) {46
MODEM_STATUS = 1 << 3;47
RECEIVER_LINE_STATUS = 1 << 2;48
TX_HOLDING_REGISTER_EMPTY = 1 << 1;49
RECEIVED_DATA_AVAILABLE = 1 << 0;50
}51
}52
53
// offset 0x2, write, FIFO Control Register (FCR)54
bitfield! {55
#[derive(Copy, Clone, Default)]56
pub struct FifoControl(u8);57
impl Debug;58
rx_trigger_size_bits, _: 7, 6;59
dma_mode, _: 3;60
tx_reset, _: 2;61
rx_reset, _: 1;62
fifo_enabled, _: 0;63
}64
65
impl FifoControl {66
pub fn rx_trigger_size(&self) -> usize {67
match self.rx_trigger_size_bits() {68
0b00 => 1,69
0b01 => 4,70
0b10 => 8,71
0b11 => 14,72
_ => unreachable!(),73
}74
}75
}76
77
// offset 0x2, read, Interrupt Identification Register78
bitfield! {79
#[derive(Copy, Clone)]80
pub struct InterruptIdentification(u8);81
impl Debug;82
fifo_enabled, _: 7, 6;83
interrupt_id, set_interrupt_id: 3,1;84
no_pending, set_no_pending: 0; // Interrupt Pending Bit85
}86
87
impl InterruptIdentification {88
pub fn set_fifo_enabled(&mut self) {89
self.0 |= 0b11 << 6;90
}91
92
pub fn clear_fifi_enabled(&mut self) {93
self.0 &= !(0b11 << 6);94
}95
96
pub fn set_rx_data_available(&mut self) {6x97
self.0 = (self.0 & !0b1111) | 0b0100;6x98
}6x99
100
pub fn set_tx_room_empty(&mut self) {3x101
self.0 = (self.0 & !0b1111) | 0b0010;3x102
}3x103
104
pub fn clear_interrupt(&mut self) {27x105
self.0 = (self.0 & !0b1111) | 1;27x106
}27x107
}108
109
impl Default for InterruptIdentification {110
fn default() -> Self {18x111
let mut val = InterruptIdentification(0);18x112
val.clear_interrupt();18x113
val18x114
}18x115
}116
117
// offset 0x3, Line Control Register (LCR)118
bitfield! {119
#[derive(Copy, Clone)]120
pub struct LineControl(u8);121
impl Debug;122
divisor_latch_access, _: 7;123
break_, _: 6;124
stick_parity, _: 5;125
even_parity, _: 4;126
parity_enabled, _: 3;127
step_bits, _: 2;128
word_length, _: 1, 0;129
}130
131
impl Default for LineControl {132
fn default() -> Self {18x133
LineControl(0b00000011) // 8 data bits as default18x134
}18x135
}136
137
// offset 0x4, Modem Control Register138
bitfield! {139
#[derive(Copy, Clone, Default)]140
pub struct ModemControl(u8);141
impl Debug;142
loop_back, _: 4;143
out_2, _: 3;144
out_1, _: 2;145
request_to_send, _: 1;146
data_terminal_ready, _: 0; // Data Terminal Ready147
}148
149
// offset 0x5, Line Status Register (LSR)150
bitflags! {151
pub struct LineStatus(u8) {152
ERROR_IN_RX_FIFO = 1 << 7;153
TX_EMPTY = 1 << 6;154
TX_HOLDING_REGISTER_EMPTY = 1 << 5;155
BREAK_INTERRUPT = 1 << 4;156
FRAMING_ERROR = 1 << 3;157
PARITY_ERROR = 1 << 2;158
OVERRUN_ERROR = 1 << 1;159
DATA_READY = 1 << 0;160
}161
}162
163
impl Default for LineStatus {164
fn default() -> Self {18x165
LineStatus::TX_EMPTY | LineStatus::TX_HOLDING_REGISTER_EMPTY18x166
}18x167
}168
169
#[derive(Default, Debug)]170
struct SerialReg {171
interrupt_enable: InterruptEnable, // 0x1, Interrupt Enable Register (IER)172
#[allow(dead_code)]173
fifo_control: FifoControl, // 0x2, write, FIFO Control Register (FCR)174
interrupt_identification: InterruptIdentification, // 0x2, read, Interrupt Identification Register175
line_control: LineControl, // 0x3, Line Control Register (LCR)176
modem_control: ModemControl, // 0x4, Modem Control Register (MCR)177
line_status: LineStatus,178
modem_status: u8, // 0x6, Modem Status Register (MSR)179
scratch: u8, // 0x7, Scratch Register (SCR)180
divisor: u16,181
data: VecDeque<u8>,182
}183
184
#[derive(Debug)]185
pub struct Serial<M: MsiSender, C> {186
name: Arc<str>,187
io_apci: Arc<IoApic<M>>,188
pin: u8,189
reg: Arc<Mutex<SerialReg>>,190
console: Arc<C>,191
_thread: ConsoleThread,192
}193
194
impl<M, C> Mmio for Serial<M, C>195
where196
M: MsiSender,197
C: Console,198
for<'a> &'a C: Read + Write,199
{200
fn size(&self) -> u64 {3x201
83x202
}3x203
204
fn read(&self, offset: u64, _size: u8) -> Result<u64, mem::Error> {63x205
let mut reg = self.reg.lock();63x206
let ret = match offset as u16 {63x207
DIVISOR_LATCH_LSB if reg.line_control.divisor_latch_access() => reg.divisor as u8,12x208
DIVISOR_LATCH_MSB if reg.line_control.divisor_latch_access() => {3x209
(reg.divisor >> 8) as u83x210
}211
RX_BUFFER_REGISTER => {212
if reg.data.len() <= 1 {9x213
reg.line_status &= !LineStatus::DATA_READY;9x214
}9x215
reg.data.pop_front().unwrap_or(0xff)9x216
}217
INTERRUPT_ENABLE_REGISTER => reg.interrupt_enable.bits(),218
INTERRUPT_IDENTIFICATION_REGISTER => {219
let ret = reg.interrupt_identification.0;9x220
reg.interrupt_identification.clear_interrupt();9x221
ret9x222
}223
LINE_CONTROL_REGISTER => reg.line_control.0,6x224
MODEM_CONTROL_REGISTER => reg.modem_control.0,3x225
LINE_STATUS_REGISTER => reg.line_status.bits(),21x226
MODEM_STATUS_REGISTER => reg.modem_status,3x227
SCRATCH_REGISTER => reg.scratch,3x228
_ => {229
log::error!("{}: read unreachable offset {offset:#x}", self.name,);3x230
0x03x231
}232
};233
Ok(ret as u64)63x234
}63x235
236
fn write(&self, offset: u64, _size: u8, val: u64) -> mem::Result<Action> {48x237
let byte = val as u8;48x238
let mut reg = self.reg.lock();48x239
match offset as u16 {48x240
DIVISOR_LATCH_LSB if reg.line_control.divisor_latch_access() => {9x241
reg.divisor = (reg.divisor & 0xff00) | byte as u16;3x242
}3x243
DIVISOR_LATCH_MSB if reg.line_control.divisor_latch_access() => {15x244
reg.divisor = (reg.divisor & 0x00ff) | ((byte as u16) << 8);3x245
}3x246
TX_HOLDING_REGISTER => {247
if reg.modem_control.loop_back() {6x248
reg.data.push_back(byte);3x249
if reg3x250
.interrupt_enable3x251
.contains(InterruptEnable::RECEIVED_DATA_AVAILABLE)3x252
{3x253
reg.interrupt_identification.set_rx_data_available();3x254
self.send_irq();3x255
}3x256
reg.line_status |= LineStatus::DATA_READY;3x257
} else {258
let _ = self.console.as_ref().write(&[byte]);3x259
if reg3x260
.interrupt_enable3x261
.contains(InterruptEnable::TX_HOLDING_REGISTER_EMPTY)3x262
{263
reg.interrupt_identification.set_tx_room_empty();3x264
self.send_irq()3x265
}266
}267
}268
INTERRUPT_ENABLE_REGISTER => {12x269
reg.interrupt_enable = InterruptEnable::from_bits_truncate(byte);12x270
}12x271
FIFO_CONTROL_REGISTER => {}3x272
LINE_CONTROL_REGISTER => {6x273
reg.line_control = LineControl(byte);6x274
}6x275
MODEM_CONTROL_REGISTER => {6x276
reg.modem_control = ModemControl(byte);6x277
}6x278
LINE_STATUS_REGISTER => {}279
MODEM_STATUS_REGISTER => {}3x280
SCRATCH_REGISTER => {3x281
reg.scratch = byte;3x282
}3x283
_ => log::error!("{}: write unreachable offset {:#x}", self.name, offset),3x284
}285
Ok(Action::None)48x286
}48x287
}288
289
impl<M, C> Pause for Serial<M, C>290
where291
M: MsiSender,292
{293
fn pause(&self) -> device::Result<()> {3x294
Ok(())3x295
}3x296
297
fn resume(&self) -> device::Result<()> {3x298
Ok(())3x299
}3x300
}301
302
impl<M, C> MmioDev for Serial<M, C>303
where304
M: MsiSender,305
C: Console,306
for<'a> &'a C: Read + Write,307
{308
}309
310
struct SerialRecv<M: MsiSender> {311
pub name: Arc<str>,312
pub io_apci: Arc<IoApic<M>>,313
pub pin: u8,314
pub reg: Arc<Mutex<SerialReg>>,315
}316
317
impl<M: MsiSender> UartRecv for SerialRecv<M> {318
fn receive(&self, bytes: &[u8]) {6x319
let mut reg = self.reg.lock();6x320
reg.data.extend(bytes);6x321
if reg6x322
.interrupt_enable6x323
.contains(InterruptEnable::RECEIVED_DATA_AVAILABLE)6x324
{325
reg.interrupt_identification.set_rx_data_available();3x326
if let Err(e) = self.io_apci.service_pin(self.pin) {3x327
log::error!("{}: sending interrupt: {e:?}", self.name);328
}3x329
}3x330
reg.line_status |= LineStatus::DATA_READY;6x331
}6x332
}333
334
impl<M, C> Serial<M, C>335
where336
M: MsiSender,337
C: Console,338
for<'a> &'a C: Read + Write,339
{340
pub fn new(base_port: u16, io_apci: Arc<IoApic<M>>, pin: u8, console: C) -> Result<Self> {18x341
let reg = Arc::new(Mutex::new(SerialReg::default()));18x342
let console = Arc::new(console);18x343
let name: Arc<str> = Arc::from(format!("serial_{base_port:#x}"));18x344
let uart_recv = SerialRecv {18x345
io_apci: io_apci.clone(),18x346
pin,18x347
name: name.clone(),18x348
reg: reg.clone(),18x349
};18x350
let thread = ConsoleThread::new(name.clone(), uart_recv, console.clone())?;18x351
let serial = Serial {18x352
name,18x353
reg,18x354
pin,18x355
io_apci,18x356
console,18x357
_thread: thread,18x358
};18x359
Ok(serial)18x360
}18x361
362
fn send_irq(&self) {6x363
if let Err(e) = self.io_apci.service_pin(self.pin) {6x364
log::error!("{}: sending interrupt: {e:?}", self.name);365
}6x366
}6x367
}368
369
#[cfg(test)]370
#[path = "serial_test.rs"]371
mod tests;372